1.INTRODUCTION

Education is an important part of society which directly influences mankind’s development in the future. New York City is one of the most active cities all over the world, which longs for more talents and expects better education on citizens. Thus, in order to figure out the education condition in NYC and give some advice to policy makers and students and their parents on school selection and self-improvement, we expect to analyze some local schools’ and students’ datasets.

We concentrated on analyses of K-12 and senior education. We divided our assignment into three part: 1) Students’ information visualization and analysis. The analysis is basically on students’ graduation rates, math and ELA grades, SAT scores and educated rate with respect to ethnicity, gender, and English language level; 2) Schools’ information visualization and analysis. In this part, we specifically study schools’ rating and progress condition by years and areas; 3) Further analysis and suggestions. Based on the visualization and analysis combining with policies and social factors, we could give some suggestions for policy makers and for students and their parents.

Exhilarated by our idea, we looked for the open dataset on NYC and education information. Fortunately, there are a lot of dataset for NYC and the official website helps us much. Our datasets came from the NYC open data(http://opendata.cityofnewyork.us/) and the government website on education department (http://schools.nyc.gov/default.htm). From NYC Open Data, we could find many datasets on local schools in Education selection below. We selected some csv format datasets on school information for our analysis objects and gained some geo-information for further map visualization. And in the official website, we finally surprisingly found the column named “Performance and Accountability” on the left side of the webpage, and then gained students’ performance and graduation information in “NYC data”. These two websites are the source of our dataset. And we hope that our data visualization and analysis could help people a lot on education domain.

2. TEAM

Our group name, EDAsquare, stands for Education Data Analysis on Explore Data Analysis. EDAsquare Team member: Yunsi Zhang(yz3012), Kunyi Liu(kl2912), Zeyu Ye(zy2232).

Based on the division of our project above, we had our own tasks. Yunsi and Kunyi were responsible for the first part and Zeyu was responsible for the second part. The last part was completed by us together.

Specifically, Yunsi visualized the data of students’ Math and ELA grades with histogram, parallel coordinate, heatmap and covariance matrix to analyze students’ performance in different boroughs, genders, and ethnicity and explore the relationship between Math and ELA grades. Kunyi used the histogram, heatmap, scatter plot and parallel coordinate to visualize the data of graduation rate and SAT scores and analyzed students’ performance of their graduation with respect to ethnicity, gender, and English language level to explore the effects of these factors on students’ performance. For the data of school information, Zeyu used heatmap and parallel coordinates plot and histogram to visualize quality and progress of schools for different years and boroughs and analyze the change of them. Besides, he analyzed the proportion of people educated in NYC for different age group (School age(5-17) and over 65) for years. Furthermore, we built an interactive map to show our visualization.

For the last part, we communicated results of our own tasks and combined them together to look for more insights into these data. With collision sparks of wisdom, we proposed new visualizations that are likely to give us some other insights into our data. After we figured out the education condition in NYC, we gave some suggestions to policy makers, students, and their parents.

3. ANALYSIS of DATA QUALITY

Overall, the datasets quite matches our needs on analyzing NYC K-12 education.

Here are some cons of original datasets and challenges we were faced when we firstly gained them from the offical website of New York City Department of Education(NYCDOE). 1. We could not get the data of graduation rate in 2013-2016 and the Math and ELA score in 2001-2006 and because it is not provided on the website of the department of education. Therefore, we cannot analyze the relationship between them in those years. 2. Besides, there are some missing data in the dataset, which makes some charts incomplete and we cannot use them such as parallel coordinate. 3. There are also some reduplicated data that we need to clean. 4. There are some wrong data in the dataset of location, including wrong borough and wrong zip code. 5. We need to change the grade A, B, C, D to an integer to build a chart.

Data Quality

library(extracat)
graduate_eth_na<-graduate_eth[colSums(is.na(graduate_eth))>0]
image(missing_data.frame(graduate_eth_na[,]),cex.lab = .5)

Although the datasets are dirty, they provided detailed information about education and divided data into different groups namely year group, district, Ethnicity, Gender, SWD, and ELL, which enables us to get an insight into NYC K-12 education and save our time of data processing.

4. EXECUTIVE SUMMARY

Our project concentrated on analyses of NYC K-12 education. We have built an interactive Heatmap of NYC school district on a web to show the graduation rate of different districts. We found that education levels and students’ performances are various from different districts, which may related to some social factors discussed followed.

Here is our interactive map link: https://plnkr.co/edit/n3D6hCEnh2kdNK8pEdym?p=preview

The codes for our interactive map are in left columns. You can click the right-top blue button to launch a previewer to a separate window which is our website interface. The left part of the web is the map of NYC school districts. The darker the color of a district is, the higher the graduation rate of this district is. The right part of the web is two stacked bar charts showing the graduation results of a certain district of different years. The top one shows the composition of cohorts, including the rate of Graduation, Still Enrolled, Dropout, Skills & Achievement Commencement Credential (SACC) and Test Assessing Secondary Completion (TASC). The bottom one shows the composition of the graduation, including Advanced Regent, Regent without Advanced and Local.

[A Brief Instruction for the Interactive Map] When your mouse hovers on a district the map, the basic information of this district in 2012 is shown in the box on the left-top corner of the map. When a district is clicked on, the stacked bar charts will change to show the information of this district. When you click on the legend of a feature below a stacked bar chart, the chart will change and show the remaining features. By this way, we can choose the specific feature we are interested in to show it in the chart.

We pick two districts’ graduation result as an example: For District 26 (the screenshot for district 26): Within all the districts, District 26 have got the most excellent graduation performance over the years. According to the map part of the interactive graph, the darkness of District 26 ranks first, since the graduation rate of the district was 84.71% in 2012, which was the highest.

From the right session of the graph, the two stacked bar charts demonstrate both the composition of cohort and the composition of graduation students. In the composition of cohorts, we found out that, in District 26, the graduation rates were all above 70%, gradually raising over the years, while the dropout rates were gradually decreasing to less than 5%. In the graph of the composition of graduation, the ratio of the students with regent without advanced diplomas had shown an upward trend, reaching to the percentage over 50% in 2012, whereas there were fewer students getting local diplomas, which meant the academic performance of the students were getting better. Besides, the advanced regent rate remained similar.

For District 23 (the screenshot for district 23)

Out of all the districts, District 23 have got the least decent graduation performance over the years. According to the map part of the interactive graph, the color of District 23 is lightest, since the graduation rate of the district was below 50% in 2012, which was the lowest. From the right session of the graph, the two stacked bar charts demonstrate both the composition of cohort and the composition of graduation students. In the composition of cohorts, we found out that, in District 23, the graduation rates were generally below 50%, reaching the peak in 2004, while the still enrolled rates were gradually increasing after 2006. In the graph of the composition of graduation, the ratio of the students with regent without advanced diplomas had shown an upward trend, reaching to the percentage over 70% in 2012, whereas there were fewer students getting local diplomas. However, the Advanced Regent rate remained a relatively low level (less than 10%) over the years.

5. Main Analysis

(1) Overall Insight

NYC is a city with prosperous education development, ranging from 5-17 primary education, higher education and senior education. Here we could see the student population proportion of people in age 5-17 and senior people to NYC total population.

library(dplyr)
library(tidyr)
library(ggplot2)
library(tibble)
library(viridis)
library(grid)
library(gridExtra)
library(mi)
library(RColorBrewer)
library(scales)
library(extracat)
library(knitr)
library(vcd)
library(GGally)
#load data
loc <- read.csv("location.csv", header=TRUE, stringsAsFactors=FALSE)
loc <- loc[c(2, 3, 15, 17, 23 )]
colnames(loc) <- c("DBN", "DB", "Borough", "Zipcode", "District")
# clean
ages <- read.csv("Age.csv", header=TRUE, stringsAsFactors=FALSE)
Age2 <- ages[c(4,6,8,10,12,14,16,18,20,22)]
Age1 <- ages[c(1, 2)]
Age2 <- data.frame(lapply(Age2, function(x) as.numeric(sub("%", "", x))/100) ) 
Age <- cbind(Age1, Age2)
Age[Age == "NYC Total"]="  NYC Total"
colnames(Age) <- c("Age", "Borough", "1950", "1960", "1970", "1980", "1990", "2000", "2010", "2020", "2030", "2040")
AgeData <- Age[c(1,2,3,4,5,6,7,8,9)]
#plot
age_f <- Age[1:9] %>% gather(Year, Percent,3:9)
age_f[age_f == "School-Age (5 to 17)"] = "5-17"
age_f[age_f == "65 and over"] = "over 65"
age_f$Year = as.numeric(age_f$Year)
ggplot(age_f, aes(x = Year, y = Percent, col = Borough))+geom_line(size = 0.7, aes(linetype = Age))+scale_x_continuous(breaks = seq(1950, 2010, 10))+
  labs(title = " Percent of Total Population 1950-2010", linetype = "Age Group")

At first, we used the histogram to show the proportion of different years, but it cannot show the trend of the proportion change over these years. Therefore, we chose to visualize the data with time series. Apparently, it can give us insight into the data.

The figure above shows the change of percent of total population of two age groups, 5-17 and over 65, from 1950 to 2010. From the figure, we could figure out that in general, young group’s percent has been decreasing over these years. Specifically, the young’s percent reached a peak in 1970 and 2000, which is consistent with the fact that the growth rate reached a peak in the 1970s and 1990s.
(This information is from the data here https://www.google.com/publicdata/explore?ds=d5bncppjof8f9_&met_y=sp_pop_grow&idim=country%3AUSA%3AIND%3ACAN&hl=en&dl=en#!ctype=l&strail=false&bcs=d&nselm=h&met_y=sp_pop_grow&scale_y=lin&ind_y=false&rdim=region&idim=country:USA&ifdim=region&hl=en_US&dl=en&ind=false).
And old group’s percent has been increasing over these years, which is consistent with the ageing of population.

Then we use time-series to analyze future education condition.

#prediction
age <- Age %>% gather(Year, Percent,3:12)
age[age == "School-Age (5 to 17)"] = "5-17"
age[age == "65 and over"] = "over 65"
age$Year = as.numeric(age$Year)
ggplot(age, aes(x = Year, y = Percent, col = Borough))+geom_line(size = 0.7, aes(linetype = Age))+scale_x_continuous(breaks = seq(1950, 2040, 10))+
  labs(title = " Percent of Total Population 1950-2040", linetype = "Age Group") + 
  theme_grey(16)

In this figure, data predicted from the ageing of population is added.

(2) Math and ELA Score Analysis in Grade 3 ~ 8 from 2006 ~ 2016

#import math dataset
column_name = c("District", "Grade", "Year", "Category", "Number_Tested", "Mean_Scale_Score", "level1", "level1_per", "level2", "level2_per", "level3", "level3_per", "level4", "level4_per", "level3&4", "level3&4_per")
#data of 2013-2016
math_all_stu_1316 <- read.csv("math_all_stu2013-2016.csv", skip = 6, col.names = column_name)
math_ethnicity_1316 <- read.csv("math_ethnicity13-16.csv", skip = 6, col.names = column_name)
math_gender_1316 <- read.csv("math_gender13-16.csv", skip = 6, col.names = column_name)
math_swd_1316 <- read.csv("math_swd13-16.csv", skip = 6, col.names = column_name)
math_ell_1316 <- read.csv("math_ell13-16.csv", skip = 6, col.names = column_name)
math_all_stu_1316[math_all_stu_1316 == "s"] = NA
math_ethnicity_1316[math_ethnicity_1316 == "s"] = NA
math_gender_1316[math_gender_1316 == "s"] = NA
math_swd_1316[math_swd_1316 == "s"] = NA
math_ell_1316[math_ell_1316 == "s"] = NA
math_all_stu_1316$Mean_Scale_Score = as.numeric(as.character(math_all_stu_1316$Mean_Scale_Score))
math_ethnicity_1316$Mean_Scale_Score = as.numeric(as.character(math_ethnicity_1316$Mean_Scale_Score))
math_gender_1316$Mean_Scale_Score = as.numeric(as.character(math_gender_1316$Mean_Scale_Score))
math_swd_1316$Mean_Scale_Score = as.numeric(as.character(math_swd_1316$Mean_Scale_Score))
math_ell_1316$Mean_Scale_Score = as.numeric(as.character(math_ell_1316$Mean_Scale_Score))
math_ell_1316$level1 = as.numeric(as.character(math_ell_1316$level1))
math_ell_1316$level2 = as.numeric(as.character(math_ell_1316$level2))
math_ell_1316$level3 = as.numeric(as.character(math_ell_1316$level3))
math_ell_1316$level4 = as.numeric(as.character(math_ell_1316$level4))
#data of 2006-2012
math_all_stu_0612 <- read.csv("math_all_stu_0612.csv", skip = 6, col.names = column_name)
math_ethnicity_0612 <- read.csv("math_ethnicity_0612.csv", skip = 6, col.names = column_name)
math_gender_0612 <- read.csv("math_gender_0612.csv", skip = 6, col.names = column_name)
math_swd_0612 <- read.csv("math_swd06-12.csv", skip = 6, col.names = column_name)
math_ell_0612 <- read.csv("math_ell06-12.csv", skip = 6, col.names = column_name)
math_all_stu_0612[math_all_stu_0612 == "s"] = NA
math_ethnicity_0612[math_ethnicity_0612 == "s"] = NA
math_gender_0612[math_gender_0612 == "s"] = NA
math_swd_0612[math_swd_0612 == "s"] = NA
math_ell_0612[math_ell_0612 == "s"] = NA
math_all_stu_0612$Mean_Scale_Score = as.numeric(as.character(math_all_stu_0612$Mean_Scale_Score))
math_ethnicity_0612$Mean_Scale_Score = as.numeric(as.character(math_ethnicity_0612$Mean_Scale_Score))
math_gender_0612$Mean_Scale_Score = as.numeric(as.character(math_gender_0612$Mean_Scale_Score))
math_swd_0612$Mean_Scale_Score = as.numeric(as.character(math_swd_0612$Mean_Scale_Score))
math_ell_0612$Mean_Scale_Score = as.numeric(as.character(math_ell_0612$Mean_Scale_Score))
math_ethnicity_1316 <- data.frame(math_ethnicity_1316)

Here we processed original Math score data. During the process of input math data, we removed several useless lines at the beginning of the csv, and reset the column names. Then, we set the missing data, which was “s” in the original dataset, as “NA”s in order to avoid errors in following analyses. Next, I reset the type of columns for further analysis, i.e. we set the columns with missing value as numeric (which is factor because of “s”) to avoid mistakes in following numerical calculation. And here is a trick that when converting type factor to type numeric, you have to firstly change it to type character then type numeric, because R treat values with type factor as labels and ignore the value of it. If you set factor as numeric, the numeric value is random, which is not appropriate to our analyses.

##ELA
#import ELA dataset
column_name = c("District", "Grade", "Year", "Category", "Number_Tested", "Mean_Scale_Score", "level1", "level1_per", "level2", "level2_per", "level3", "level3_per", "level4", "level4_per", "level3&4", "level3&4_per")
#data of 2013-2016
ela_all_stu_1316 <- read.csv("ela_all_1316.csv", skip = 6, col.names = column_name)
ela_ethnicity_1316 <- read.csv("ela_ethnicity_1316.csv", skip = 6, col.names = column_name)
ela_gender_1316 <- read.csv("ela_gender_1316.csv", skip = 6, col.names = column_name)
ela_swd_1316 <- read.csv("ela_swd_1316.csv", skip = 6, col.names = column_name)
ela_ell_1316 <- read.csv("ela_ell_1316.csv", skip = 6, col.names = column_name)
ela_all_stu_1316[ela_all_stu_1316 == "s"] = NA
ela_ethnicity_1316[ela_ethnicity_1316 == "s"] = NA
ela_gender_1316[ela_gender_1316 == "s"] = NA
ela_swd_1316[ela_swd_1316 == "s"] = NA
ela_ell_1316[ela_ell_1316 == "s"] = NA
ela_all_stu_1316$Mean_Scale_Score = as.numeric(as.character(ela_all_stu_1316$Mean_Scale_Score))
ela_ethnicity_1316$Mean_Scale_Score = as.numeric(as.character(ela_ethnicity_1316$Mean_Scale_Score))
ela_gender_1316$Mean_Scale_Score = as.numeric(as.character(ela_gender_1316$Mean_Scale_Score))
ela_swd_1316$Mean_Scale_Score = as.numeric(as.character(ela_swd_1316$Mean_Scale_Score))
ela_ell_1316$Mean_Scale_Score = as.numeric(as.character(ela_ell_1316$Mean_Scale_Score))
ela_ell_1316$level1 = as.numeric(as.character(ela_ell_1316$level1))
ela_ell_1316$level2 = as.numeric(as.character(ela_ell_1316$level2))
ela_ell_1316$level3 = as.numeric(as.character(ela_ell_1316$level3))
ela_ell_1316$level4 = as.numeric(as.character(ela_ell_1316$level4))
#data of 2006-2012
ela_all_stu_0612 <- read.csv("ela_all_0612.csv", skip = 6, col.names = column_name)
ela_ethnicity_0612 <- read.csv("ela_ethnicity_0612.csv", skip = 6, col.names = column_name)
ela_gender_0612 <- read.csv("ela_gender_0612.csv", skip = 6, col.names = column_name)
ela_swd_0612 <- read.csv("ela_swd_0612.csv", skip = 6, col.names = column_name)
ela_ell_0612 <- read.csv("ela_ell_0612.csv", skip = 6, col.names = column_name)
ela_all_stu_0612[ela_all_stu_0612 == "s"] = NA
ela_ethnicity_0612[ela_ethnicity_0612 == "s"] = NA
ela_gender_0612[ela_gender_0612 == "s"] = NA
ela_swd_0612[ela_swd_0612 == "s"] = NA
ela_ell_0612[ela_ell_0612 == "s"] = NA
ela_all_stu_0612$Mean_Scale_Score = as.numeric(as.character(ela_all_stu_0612$Mean_Scale_Score))
ela_ethnicity_0612$Mean_Scale_Score = as.numeric(as.character(ela_ethnicity_0612$Mean_Scale_Score))
ela_gender_0612$Mean_Scale_Score = as.numeric(as.character(ela_gender_0612$Mean_Scale_Score))
ela_swd_0612$Mean_Scale_Score = as.numeric(as.character(ela_swd_0612$Mean_Scale_Score))
ela_ell_0612$Mean_Scale_Score = as.numeric(as.character(ela_ell_0612$Mean_Scale_Score))

Since ELA data had the same data structure as Math data, here we did the similar data processing as for Math data described before. I removed useless rows and set column names when inputing thr data, and then set “s” as NAs. Finally we adjusted the type of data for preparation for data analyses.

a) Heatmap on Math and ELA score by district 2006 ~ 2016

# math scores on all student
# The heatmap with district, year, and fill mean score for math on year 2006 to year 2016
math_allstu = rbind(math_all_stu_0612, math_all_stu_1316)
ggplot(math_allstu, aes(x = Year, y = District, fill = Mean_Scale_Score)) + 
    geom_tile() +
    scale_fill_viridis() +
    scale_x_continuous(breaks = seq(2006, 2016, 1)) +
    scale_y_continuous(breaks = seq(1, 32, 1)) +
    coord_flip() +
    labs(title = "All student in grades 3 ~ 8 Math Mean Score 2006 ~ 2016", x = "Year", y = "District") 

The reason we used heatmap here was that heatmap could explicitly show the difference between years 2006 ~ 2012 and years 2013 to 2016. Because the data came from two datasets, we used “rbind” to bind them together to gain general information of 3~8 grade student math scores by district from 2006 ~ 2016.

This plot clearly indicates that students’ math scores significantly decreased after year 2012. We find the information online (http://www.nydailynews.com/new-york/education/city-students-scores-dramatic-plunge-new-standardized-tests-article-1.1419973 ) to explain this phenomenon. " Only 31% of New York State students in grades 3 to 8 passed the 2013 math and reading tests, down from 55% in English and 65% in math in 2012 on easier tests." This report reported that the sudden drop on math score did not reflect a drop in performance but rather a raising of standards on exams. In fact, “starting in 2013, the NY State Education Department (NYSED) changed the exams to be Common Core aligned.”(citing from dataset introduction) This fact has verified our data exploration on math mean scores from year 2006 to 2016.

# ELA(English Language Arts) scores on all student
# The heatmap with district, year, and fill mean score for math on year 2006 to year 2016
ela_allstu = rbind(ela_all_stu_0612, ela_all_stu_1316)
ggplot(ela_allstu, aes(x = Year, y = District, fill = Mean_Scale_Score)) + 
    geom_tile() +
    scale_fill_viridis() +
    scale_x_continuous(breaks = seq(2006, 2016, 1)) +
    scale_y_continuous(breaks = seq(1, 32, 1)) +
    coord_flip() +
    labs(title = "All student in grades 3 ~ 8 ELA Mean Score 2006 ~ 2016", x = "Year", y = "District") 

This plot indicates that the raising standards of exams led to much lower average ELA score as well. We could see both math and ELA (English Language Arts) score decrease by the similar scale.

(2) Comparison of scores with district by 2006 ~ 2012 and 2013 ~ 2016

# Math
# Seperate Math scores by year 2006 ~ 2012 and 2013 ~ 2016
p0612 = ggplot(math_all_stu_0612, aes(x = Year, y = District, fill = Mean_Scale_Score)) + 
    geom_tile() +
    scale_fill_viridis() +
    scale_x_continuous(breaks = seq(2006, 2016, 1)) +
    scale_y_continuous(breaks = seq(1, 32, 1)) +
    coord_flip() +
    labs(title = "All student Math Mean Score by District 2006 ~ 2012", x = "Year", y = "District")
p1316 = ggplot(math_all_stu_1316, aes(x = Year, y = District, fill = Mean_Scale_Score)) + 
    geom_tile() +
    scale_fill_viridis() +
    scale_x_continuous(breaks = seq(2006, 2016, 1)) +
    scale_y_continuous(breaks = seq(1, 32, 1)) +
    coord_flip() +
    labs(title = "All student Math Mean Score by District 2013 ~ 2016", x = "Year", y = "District")
grid.arrange(p0612, p1316, nrow = 2)

Here we also used heatmap to clearly show the performance differences within and across year groups and compare students’ performance by different districts.

According to two graphs above, we can indicate that: 1) As time went by, students’ performances on math exam became better than before. 2) As the difficulty of math exam increased from year 2006 ~ 2012 to 2013 ~ 2016, the performance differences we larger than before. 3) The prominent two district were 26 and 2, which might correspond to some social factors, such as the income, which would be discussed in the final part of Main Analysis.

# ELA
# Seperate ELA scores by year 2006 ~ 2012 and 2013 ~ 2016
ela_p0612 = ggplot(ela_all_stu_0612, aes(x = Year, y = District, fill = Mean_Scale_Score)) + 
    geom_tile() +
    scale_fill_viridis() +
    scale_x_continuous(breaks = seq(2006, 2016, 1)) +
    scale_y_continuous(breaks = seq(1, 32, 1)) +
    coord_flip() +
    labs(title = "All student ELA Mean Score by District 2006 ~ 2012", x = "Year", y = "District")
ela_p1316 = ggplot(ela_all_stu_1316, aes(x = Year, y = District, fill = Mean_Scale_Score)) + 
    geom_tile() +
    scale_fill_viridis() +
    scale_x_continuous(breaks = seq(2006, 2016, 1)) +
    scale_y_continuous(breaks = seq(1, 32, 1)) +
    coord_flip() +
    labs(title = "All student ELA Mean Score by District 2013 ~ 2016", x = "Year", y = "District")
grid.arrange(ela_p0612, ela_p1316, nrow = 2)

By this plot, we found that heatmap of Math and ELA performances were similar. In general, student mean score increased as time went by, yet ELA had expectations on year 2011 and 2014. In addition, compared with year group 2006 ~ 2012, the range of students’ mean scores on ELA enlarged as mean scores on Math. And the districts with higher average Math scores corresponded to the districts with higher average ELA scores. Thus, we referred that there might be some relationship between Math exam performances and ELA exam performances. So, we did two covariance matrices to indicate the relationship between Math and ELA.

(3) Covariance Matrices on Math and ELA exam performances

library(plyr)
math_all0612 <- math_all_stu_0612 %>% 
  mutate(year_cat = "06-12")
math_all1316 <- math_all_stu_1316 %>% 
  mutate(year_cat = "13-16")
ela_all0612 <- ela_all_stu_0612 %>% 
  mutate(year_cat = "06-12")
ela_all1316 <- ela_all_stu_1316 %>% 
  mutate(year_cat = "13-16")
math_all = rbind(math_all0612, math_all1316)
ela_all = rbind(ela_all0612, ela_all1316)
math_allstu_rn <- rename(math_all, c("District" = "math_district", "Grade" = "math_grade", "Year" = "math_year", "Category" = "math_category", "Number_Tested" = "math_num_test", "Mean_Scale_Score" = "math_mean", "level1" = "math_level1", "level1_per" = "math_level1_per", "level2" = "math_level2", "level2_per" = "math_level2_per", "level3" = "math_level3", "level3_per" = "math_level3_per", "level4" = "math_level4", "level4_per" = "math_level4_per", "level3.4" = "math_level3.4", "level3.4_per" = "math_level3.4_per", "year_cat" = "math_year_cat"))
ela_allstu_rn <- rename(ela_all, c("District" = "ela_district", "Grade" = "ela_grade", "Year" = "ela_year", "Category" = "ela_category", "Number_Tested" = "ela_num_test", "Mean_Scale_Score" = "ela_mean", "level1" = "ela_level1", "level1_per" = "ela_level1_per", "level2" = "ela_level2", "level2_per" = "ela_level2_per", "level3" = "ela_level3", "level3_per" = "ela_level3_per", "level4" = "ela_level4", "level4_per" = "ela_level4_per", "level3.4" = "ela_level3.4", "level3.4_per" = "ela_level3.4_per", "year_cat" = "ela_year_cat"))
math_ela <- cbind(math_allstu_rn, ela_allstu_rn) 
math_ela <- cbind("id" = rownames(math_ela), math_ela)
df1 <- select(math_ela,id,starts_with("m"))
df2 <- select(math_ela,id,starts_with("e"))
# math and ela comparison
mmean <- df1 %>% 
  select(id, math_district, math_mean, math_year_cat) %>% 
  gather(math_var,math_mean,-id, -math_district, -math_year_cat) %>% 
  rename(., c("math_district" = "District", "math_mean" = "value", "math_year_cat" = "year_cat")) 
mlevel1_per <- df1 %>% 
  select(id,math_district, math_level1_per, math_year_cat) %>% 
  gather(math_var,math_level1_per,-id, -math_district, -math_year_cat) %>% 
  rename(., c("math_district" = "District", "math_level1_per" = "value", "math_year_cat" = "year_cat"))
mlevel2_per <- df1 %>% 
  select(id, math_district, math_level2_per, math_year_cat) %>% 
  gather(math_var,math_level2_per,-id, -math_district, -math_year_cat) %>% 
  rename(., c("math_district" = "District", "math_level2_per" = "value", "math_year_cat" = "year_cat"))
mlevel3_per <- df1 %>% 
  select(id, math_district, math_level3_per, math_year_cat) %>% 
  gather(math_var,math_level3_per,-id, -math_district, -math_year_cat) %>% 
  rename(., c("math_district" = "District", "math_level3_per" = "value", "math_year_cat" = "year_cat"))
mlevel4_per <- df1 %>% 
  select(id, math_district, math_level4_per, math_year_cat) %>% 
  gather(math_var,math_level4_per,-id, -math_district, -math_year_cat) %>% 
  rename(., c("math_district" = "District", "math_level4_per" = "value", "math_year_cat" = "year_cat"))
dftm <- rbind(mlevel1_per, mlevel2_per) %>% 
  rbind(., mlevel3_per) %>% 
  rbind(., mlevel4_per)
emean <- df2 %>% 
  select(id, ela_district, ela_mean, ela_year_cat) %>% 
  gather(ela_var,ela_mean,-id, -ela_district, -ela_year_cat) %>% 
  rename(., c("ela_district" = "District", "ela_mean" = "value", "ela_year_cat" = "year_cat"))
elevel1_per <- df2 %>% 
  select(id,ela_district, ela_level1_per, ela_year_cat) %>% 
  gather(ela_var,ela_level1_per,-id, -ela_district, -ela_year_cat) %>% 
  rename(., c("ela_district" = "District", "ela_level1_per" = "value", "ela_year_cat" = "year_cat"))
elevel2_per <- df2 %>% 
  select(id,ela_district, ela_level2_per, ela_year_cat) %>% 
  gather(ela_var,ela_level2_per,-id, -ela_district, -ela_year_cat) %>% 
  rename(., c("ela_district" = "District", "ela_level2_per" = "value", "ela_year_cat" = "year_cat"))
elevel3_per <- df2 %>% 
  select(id,ela_district, ela_level3_per, ela_year_cat) %>% 
  gather(ela_var,ela_level3_per,-id, -ela_district, -ela_year_cat) %>% 
  rename(., c("ela_district" = "District", "ela_level3_per" = "value", "ela_year_cat" = "year_cat"))
elevel4_per <- df2 %>% 
  select(id,ela_district, ela_level4_per, ela_year_cat) %>% 
  gather(ela_var,ela_level4_per,-id, -ela_district, -ela_year_cat) %>% 
  rename(., c("ela_district" = "District", "ela_level4_per" = "value", "ela_year_cat" = "year_cat"))
dfte <-rbind(elevel1_per, elevel2_per) %>% 
  rbind(., elevel3_per) %>% 
  rbind(., elevel4_per)
dft <- dftm %>% 
  left_join(dfte, by="id")
df_mean <- mmean %>% 
  left_join(emean, by = "id")
ggplot(data = dft,aes(x = value.x, y = value.y)) +
  geom_point(aes(col = year_cat.x), alpha = 0.05) +
  geom_smooth(aes(linetype = year_cat.x), fill = NA, size = 0.5) +
  facet_grid(math_var ~ ela_var) +
  labs(title = "Covariance Matrix on Math and ELA scores on grades 3 ~ 8 2006 ~ 2012 by levels (1)", x = "ELA Performane Levels Proportion", y = "Math Performance Levels Proportion", linetype = "Year Group Line", col = "Year Group Point")

Because of the similar looks on heatmaps of Math and ELA, we wanted to validate a hypothesis that student with higher scores on Math or ELA performs better in another subject as well in general. Thus, we chose Covariance Matrix to indicate the possible relationship.

However, because the function “pairs” and “plot” could not clearly indicate the trends by different categories, we did a much complex procedure to draw the covairance matrix plot. The challege we met was combining the useful information into one dataframe and then we could use ggplot2 to plot what we wanted. We use package “dplyr” to select and gather the data. Finally we could figure out the trend with ELA performances and Math performances by year group, which avoided errors caused by different exam standards. And the reason why we used feature “levels” instead of feature “scores” here was also the same.

According to the graph above, especially the plots in diagonal, we could indicate that the porprotion of students in levelN in Math exams were almost linearly related to the one of students in levelN, which might show that students with higher Math scores might have higher ELA score as well. Obviously, This graph validated our hypothesis.

# Mean covariance
ggplot(data = df_mean,aes(x = value.x, y = value.y)) +
  geom_point(aes(col = year_cat.x), alpha = 0.2) +
  geom_smooth(aes(linetype = year_cat.x), col = "black", size = 0.5) +
  facet_grid(math_var ~ ela_var) +
  labs(title = "Covariance Matrix on Math and ELA scores on grades 3 ~ 8 2006 ~ 2012 by Mean Score", x = "ELA score", y = "Math score")

Here we used mean scores to indicate the general relationship between Ela and Math by year categories. We could find that in 2006 ~ 2016, all students’ Math and ELA mean scores had positive correlation.

ggplot(data = dft,aes(x = value.x, y = value.y)) +
  geom_smooth(aes(col = as.factor(District.x), linetype = year_cat.x), fill = NA, size = 0.5) +
  facet_grid(math_var ~ ela_var) +
  guides(col = FALSE) +
  labs(title = "Covariance Matrix on Math and ELA scores on grades 3 ~ 8 2006 ~ 2012 by levels (2)", x = "ELA Performane Levels Proportion", y = "Math Performance Levels Proportion", linetype = "Year Group")

And then, we also validated the relationship between students’ Math and ELA performances by districts. Although we could not figure out the relationship for one specific district, we still could figure out the relationship in general. Clearly, for students in different districts, the positive correlation between Math and ELA scores still existed.

b) Math and ELA Score Analysis by Ethnicity

(i) Histogram on Mean score

#math_ethnicity 
#histogram
math_phist1 <- math_ethnicity_1316 %>% 
  group_by(Category) %>% 
  dplyr::summarise(mean_score = mean(Mean_Scale_Score, na.rm = TRUE)) %>% 
  mutate(Subject = "Math")
math_phist2 <- math_ethnicity_0612 %>% 
  group_by(Category) %>% 
  dplyr::summarise(mean_score = mean(Mean_Scale_Score, na.rm = TRUE)) %>% 
  mutate(Subject = "Math")
ela_phist1 <- ela_ethnicity_1316 %>% 
  group_by(Category) %>% 
  dplyr::summarise(mean_score = mean(Mean_Scale_Score, na.rm = TRUE)) %>% 
  mutate(Subject = "ELA")
ela_phist2 <- ela_ethnicity_0612 %>% 
  group_by(Category) %>% 
  dplyr::summarise(mean_score = mean(Mean_Scale_Score, na.rm = TRUE)) %>%
  mutate(Subject = "ELA")
  
pphist0612 <- rbind(math_phist2, ela_phist2)
pphist1316 <- rbind(math_phist1, ela_phist1)
subject_hist0612 <- ggplot(pphist0612, aes(x = Category, y = mean_score)) +
    geom_bar(stat = "identity", position = "dodge", aes(fill = Subject)) +
    labs(title = "2006 ~2012 Mean Score with Ethnicity", x = "Ethnicity", y = "Mean Score", fill = "Year Group")
subject_hist1316 <- ggplot(pphist1316, aes(x = Category, y = mean_score)) +
    geom_bar(stat = "identity", position = "dodge", aes(fill = Subject))+
    labs(title = "2013 ~2016 Mean Score with Ethnicity", x = "Ethnicity", y = "Mean Score", fill = "Year Group")
grid.arrange(subject_hist0612, subject_hist1316, nrow = 1)

We chose bar chart with “dodge” here because it can show ELA and Math scores together and their heights, which was convenient for readers to compare. We tried to put performances with different Ethnicity during the period 2006 ~ 2016, but that method made the differences between ethnicities unclear.

According to the graphs above, we could figure out that Asians outperformed in math and ELA exams than other ethnicities and Whites performed slightly better than other two ethnicities. And in general, Hispanics performed a bit better than Blacks. In addition, student’s math scores were higher than ELA scores in general.

(ii) Line chart on Mean score by district

# Math pcp plot
pcp_math_eth <- math_ethnicity_1316 %>% 
  group_by(Category, District) %>% 
  dplyr::summarise(mean_score=mean(Mean_Scale_Score, na.rm = TRUE)) %>% 
  mutate(year_cat = "13-16")
pcp_math_eth2 <- math_ethnicity_0612 %>% 
  group_by(Category, District) %>% 
  dplyr::summarise(mean_score = mean(Mean_Scale_Score, na.rm = TRUE)) %>% 
  mutate(year_cat = "06-12")
pcp_math <- rbind(pcp_math_eth, pcp_math_eth2)
ggplot(pcp_math, aes(x = District,  y = mean_score, col = Category)) +
  geom_line(aes(linetype = year_cat)) +
  scale_x_continuous(breaks = seq(1, 32, 1)) +
  labs(title = "Student Math Mean Score with Ethnicity and District", x = "District", y = "Mean Score", col = "Ethnicity", linetype = "Year Group")

Because this plot is easy to figure out and compare the trends compared to a bar chart, we chose line chart to indicate the overall trends by the district through different ethnicities.

According to the plot above, we found that Asians’ math scores were quite stable by district and Whites’ math scores were various through districts. The parallel coordinates plot above clearly showed that the shapes of lines by two different groups were almost the same, which indicated that students’ academic performances stayed stable with time through different districts. Moreover, what was surprised was that at District 9, 16, 17, 18, 19 and 23, Whites performed even worse than Hispanics and Blacks. There might be some reason for this phenomenon.

#ela_ethnicity 2013 ~2016
#pcp plot
pcp_ela_eth <- ela_ethnicity_1316 %>% 
  group_by(Category, District) %>% 
  dplyr::summarise(mean_score = mean(Mean_Scale_Score, na.rm = TRUE)) %>% 
  mutate(year_cat = "13-16")
pcp_ela_eth2 <- ela_ethnicity_0612 %>% 
  group_by(Category, District) %>% 
  dplyr::summarise(mean_score = mean(Mean_Scale_Score, na.rm = TRUE)) %>% 
  mutate(year_cat = "06-12")
pcp_ela <- rbind(pcp_ela_eth, pcp_ela_eth2)
ggplot(pcp_ela, aes(x = District,  y = mean_score, col = Category)) +
  geom_line(aes(linetype = year_cat)) +
  scale_x_continuous(breaks = seq(1, 32, 1)) +
  labs(title = "Student ELA Mean Score with Ethnicity and District", x = "District", y = "Reletive value", col = "Ethnicity", linetype = "Year Group")

The parallel coordinates plot above clearly showed that the shapes of lines by two different groups were almost the same, which indicated that students’ academic performances stayed stable with time through different districts. Moreover, what shocked us was that at District 7, 9, 16, 17, 18, 19 and 23 in the year 2013 to 2016, Whites performed even worse than Hispanics and Blacks, which appeared the same phenomenon in Math.

c) Math Score Analysis by Gender

(i) Line chart math score analysis by gender, grade and year group

#math_gender 
#pcp math score by gender, grade and year group
pcp_gender0612 <- math_gender_0612 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1)/sum(Number_Tested), level2_proportion = sum(level2)/sum(Number_Tested), level3_proportion = sum(level3)/sum(Number_Tested), level4_proportion = sum(level4)/sum(Number_Tested)) %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "06-12")
pcp_gender1316 <- math_gender_1316 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1)/sum(Number_Tested), level2_proportion = sum(level2)/sum(Number_Tested), level3_proportion = sum(level3)/sum(Number_Tested), level4_proportion = sum(level4)/sum(Number_Tested)) %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "13-16")
pcp_gender = rbind(pcp_gender0612, pcp_gender1316)
ggplot(pcp_gender, aes(x = as.numeric(as.factor(Levels)), y = Proportion, col = Grade, alpha = year_cat)) +
  geom_line(aes(linetype = Category)) +
  scale_alpha_discrete(range = c(0.4, 1)) +
  labs(title = "Student Math Score Levels Proportion w.r.t Gender, Grade and Year group", x = "Math Score Levels", y = "Proportion", linetype = "Gender", alpha ="Year Group", col = "Grade") 

Here we also chose line chart to indicate the overall trends of performances on levels by different grade, gender, and year group. This plot could clearly compare these three categories within one plot, which was more informative than single bar chart for readers.

According to the plot above, we could figure out some information by three dimensions with levels definition.

  1. Levels Definition: NYS Level 1: Students performing at this level are well below proficient in standards for their grade. NYS Level 2: Students performing at this level are partially proficient in standards for their grade. NYS Level 3: Students performing at this level are proficient in standards for their grade. NYS Level 4: Students performing at this level excel in standards for their grade.

  2. Gender(line and dot line): We could indicate that females performed slightly better than males in math exams, in that the proportions of females in level3 and level4 were a little bit larger than of males, while the proportions of males in level1 and level2 were a bit larger than of females.

  3. Year group (transparency in 0.4 and 1): We could clearly observe that in year group 06-12, there was the largest proportion on level3 and became less and less on level2 then level1. And around 25% students were in level4 with excellent performance. However, because of the raising standard in exams, in the year group 13-16, the proportion of students’ math performances was inversely proportional to levels. This plot coincided with our former analysis in all student math score in 2006~2012 and 2013~2016 that the differences on students’ math exam performances were greater as the degree of difficulty of math exam increased.

  4. Grade(color of lines): In the condition of the higher standard on math exams(years 2013 to 2016), the higher grade students were in, the greater score difference would be. For example, students in grade8 had larger proportion on level1 and level4 than grade5. In the condition of easier difficulty on math exams (years 2006 to 2013), the lower grade students were in, the greater score difference would be. For instance, students in grade 3 make up more than grade8 in level3 and less in level1 and level2.

# ELA analysis on gender 
#pcp ELA score by gender, grade and year group
ela_pcp_gender0612 <- ela_gender_0612 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1)/sum(Number_Tested), level2_proportion = sum(level2)/sum(Number_Tested), level3_proportion = sum(level3)/sum(Number_Tested), level4_proportion = sum(level4)/sum(Number_Tested)) %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "06-12")
ela_pcp_gender1316 <- ela_gender_1316 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1)/sum(Number_Tested), level2_proportion = sum(level2)/sum(Number_Tested), level3_proportion = sum(level3)/sum(Number_Tested), level4_proportion = sum(level4)/sum(Number_Tested)) %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "13-16")
ela_pcp_gender = rbind(ela_pcp_gender0612, ela_pcp_gender1316)
ggplot(ela_pcp_gender, aes(x = as.numeric(as.factor(Levels)), y = Proportion, col = Grade, alpha = year_cat)) +
  geom_line(aes(linetype = Category)) +
  scale_alpha_discrete(range = c(0.4, 1)) +
  labs(title = "Student ELA Score Levels Proportion w.r.t Gender, Grade and Year group", x = "ELA Score Levels", y = "Proportion", linetype = "Gender", alpha ="Year Group", col = "Grade") 

According to the plot above, we could figure out some information by three dimensions with levels definition mentioned above.

  1. Gender(line and dot line): We could indicate that females performed better than males in ELA exams with greater difference than in Math exams, in that the proportions of females in level3 and level4 were a little bit larger than of males, while the proportions of males in level1 and level2 were a bit larger than of females.

  2. Year group(transparency in 0.4 and 1): We could clearly observe that in year group 06-12, there was the largest proportion on level3 for females and the largest proportion on level2 for males. And less than 10% students were in level4 with excellent performance. However, because of the raising standard in exams, from level2 to level4 in the year group 13-16, the proportion of students’ math performances was inversely proportional to level. What surprised us was that although the standard raised and mean scores decreased sharply, students in level4 in year group 2013 ~ 2016 were more than in year group 2006 ~ 2012.

  3. Grade(color of lines): For ELA grade, it seems that students’ grades were not related to ELA scores.

(ii) Gender comparison on proportion in stacks plot

# Math
#gender comparison with stacks
ggplot(pcp_gender, aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
  geom_bar(stat = "identity") +
  facet_grid(year_cat ~ Grade) +
  labs(title = "Student Math Score Levels by gender comparison", x = "Gender", y = "Proportion", fill = "Levels") +
  theme(legend.position = "bottom") +
  guides(fill=guide_legend(reverse=TRUE))

Because the total proportions of students in different levels were 100% so we chose stacked bar charts to analyze the performance differences between Males and Females.

According to the graph above, we could figure out that the performances of females and males were almost the same, and females’ performances were slightly better than males’. This was because the proportion line of males’ performance was a little bit higher than females’, corresponding to more lower-level performances by males.

# ela
#gender comparison with stacks
ggplot(ela_pcp_gender, aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
  geom_bar(stat = "identity") +
  facet_grid(year_cat ~ Grade) +
  labs(title = "Student ELA Score Levels by gender comparison", x = "Gender", y = "Proportion", fill = "Levels") +
  theme(legend.position = "bottom") +
  guides(fill=guide_legend(reverse=TRUE))

According to the graph above, we could find that females performed better than males in all grades, especially when the exam standards raised. Moreover, this plot also corresponded to our former conclusion that students in different grades had similar performances in ELA exams. And with higher standards, students performed better in excellent (level4), much less in good (level3) and increasing amount in bad (level1).

d) Math Score Analysis by Disability Status

Analysis with grades, year group, and SWD Category on stack plot

#math SWD(student with disability)
plot_swd0612 <- math_swd_0612 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE)) %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "06-12")
plot_swd1316 <- math_swd_1316 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE))  %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "13-16")
plot_swd = rbind(plot_swd0612, plot_swd1316)
ggplot(plot_swd, aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
  geom_bar(stat = "identity") +
  facet_grid(year_cat ~ Grade) +
  labs(title = "Math Score Levels by Disability or Not", x = "Disability Status", y = "Proportion", fill = "Levels") +
  theme(legend.position = "bottom") +
  guides(fill=guide_legend(reverse=TRUE))

We also used stacked bar charts for SWD analyses as well. The comparison was very apparent by stack bar charts.

Obviously, students with a disability (SWD) performed much worse than students without a disability. Moreover, in general, the higher grade the students were in, the worse the performances of students both in SWD and notSWD groups.

#math ELA(student with disability)
ela_plot_swd0612 <- ela_swd_0612 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE)) %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "06-12")
ela_plot_swd1316 <- ela_swd_1316 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE))  %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "13-16")
ela_plot_swd = rbind(ela_plot_swd0612, ela_plot_swd1316)
ggplot(ela_plot_swd, aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
  geom_bar(stat = "identity") +
  facet_grid(year_cat ~ Grade) +
  labs(title = "ELA Score Levels by Disability or Not", x = "Disability Status", y = "Proportion", fill = "Levels") +
  theme(legend.position = "bottom") +
  guides(fill=guide_legend(reverse=TRUE))

Like the phenomenon in Math, students with a disability(SWD) performed much worse than students without a disability. Moreover, whether students were disabled or not, there were fewer students in level4 of ELA than of Math. And students with a disability accounted for the higher proportion of level1 in ELA exams than in Math exams.

e) Math Score Analysis by English Proficient Status

Analysis with grades, year group, and ELL Category on stack plot

#math Ell(English learner)
plot_ell0612 <- math_ell_0612 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE))  %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "06-12") %>% 
  ggplot(aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
   geom_bar(stat = "identity") +
   facet_grid(year_cat ~ Grade) +
   labs(title = "Math Score Levels with respect to English Proficient Status", x = "English Proficient Status", y = "Proportion", fill = "Levels") +
   #theme(legend.position = "bottom") +
   guides(fill=guide_legend(reverse=TRUE))
plot_ell1316 <- math_ell_1316 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE))  %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "13-16") %>% 
  ggplot(aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
   geom_bar(stat = "identity") +
   facet_grid(year_cat ~ Grade) +
   labs(x = "English Proficient Status", y = "Proportion", fill = "Levels") +
   #theme(legend.position = "bottom") +
   guides(fill=guide_legend(reverse=TRUE)) +
   theme(axis.text.x = element_text(angle = 30, hjust = 1))
grid.arrange(plot_ell0612, plot_ell1316, nrow = 2)

Finally, for ELL analyses, we took stacked bar charts because it was the clearest way to compare within our dataset.

According to the plot above, we could indicate the relationship between English Proficient Status and students’ performance level.

  1. The definition of ELL, EP, Former ELL: ELL: English-Language Learner. “An English language learner (often capitalized as English Language Learner or abbreviated to ELL) is a person who is learning the English language in addition to his or her native language.” (Wikipedia) EP: People with English Proficient are those who take English as mother tongue. Former ELL: Former English Language Learners. “Former English Language Learners includes any students who were classified as English Language Learners in at least one of the previous two school years.” (Official Notes for this dataset)

  2. We could find that students in ELL group performed much worse than EP groups through years 2006 to 2016. In years 2013 to 2016, official education department added a new class for English Proficient Status as “Former ELL”. We could find that except for grade3, students in Former ELL group performed better than ELL and slightly worse than EP, which might indicate that better English Language ability improved students’ understanding of math.

# ELA Ell(English learner)
ela_plot_ell0612 <- ela_ell_0612 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE))  %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "06-12") %>% 
  ggplot(aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
   geom_bar(stat = "identity") +
   facet_grid(year_cat ~ Grade) +
   labs(title = "ELA Score Levels with respect to English Proficient Status", x = "English Proficient Status", y = "Proportion", fill = "Levels") +
   #theme(legend.position = "bottom") +
   guides(fill=guide_legend(reverse=TRUE))
ela_plot_ell1316 <- ela_ell_1316 %>%
  group_by(Grade, Category) %>% 
  dplyr::summarise(level1_proportion = sum(level1, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level2_proportion = sum(level2, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level3_proportion = sum(level3, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE), level4_proportion = sum(level4, na.rm = TRUE)/sum(Number_Tested, na.rm = TRUE))  %>% 
  gather(Levels, Proportion, -Grade, -Category) %>% 
  mutate(year_cat = "13-16") %>% 
  ggplot(aes(x = Category, y = Proportion, fill = factor(Levels, levels = c("level4_proportion", "level3_proportion", "level2_proportion", "level1_proportion")))) +
   geom_bar(stat = "identity") +
   facet_grid(year_cat ~ Grade) +
   labs(x = "English Proficient Status", y = "Proportion", fill = "Levels") +
   #theme(legend.position = "bottom") +
   guides(fill=guide_legend(reverse=TRUE)) +
   theme(axis.text.x = element_text(angle = 30, hjust = 1))
grid.arrange(ela_plot_ell0612, ela_plot_ell1316, nrow = 2)

According to the plot above, we could indicate that the proficiency of English had a larger impact on ELA scores than Math scores. Students in ELL category performed much worse than students in EP and former ELL categories. However, according to the definition of “Former Ell”, we inferred that students could quickly adapt to English study environment as a former ELL in one to two years, and improve their academic performances.

(3) High School Student Performances Analysis

a) Overall Graduation Rate among Districts

col_names<-c("District","Category", "Cohort_Year", "Cohort", "num_cohort", "num_grads", "per_grads_cohort", "num_regents", "per_regents_cohort", "per_regents_grads", "num_adregents", "per_adregents_cohort", "per_adregents_grads" , "num_wadregents",   "per_wadregents_cohort", "per_wadregents_grads","num_local","per_local_cohort","per_local_grads","num_enrolled","per_enrolled_cohort","num_dropout","per_dropout_cohort","num_SACC","per_SACC_cohort","num_TASC","per_TASG_cohort")
graduate<-read.csv("2016 Graduation_Rates_Public_District_ALL.csv",skip=8,col.names =col_names)
# remove unecessary features
graduate<-graduate[-2]
cols<-col_names[6:27]
# standardize missing data 
graduate[graduate == "s"] = NA
# transform the fator into numeric 
graduate[,cols] <- apply(graduate[,cols], 2, function(x) as.numeric(x))

First and foremost, we had to do data cleaning and preprocessing to the data set in order to analyze the data. As the format of the data frame was a little messy when it was first imported to RStudio, we got to rearrange the data set related to the graduation information, such as renaming the column names, removing the unnecessary features, standardizing missing data and transforming the data type of the graduation indicators from factor into numeric.

##remove the missing data in per_grads_cohort
graduate <- graduate[complete.cases(graduate),]
graduate <- graduate%>% filter(District!=79)
  
graduate_per<- graduate%>%
    group_by(District, Cohort_Year) %>% 
   # dplyr::summarise(num_grads= sum(num_cohort))
     dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort))

From the missing data graph, we found out that a few observations are missing on all included variables. Often, this indicates a more complicated model is needed for this missingness mechanism, but we decided to remove all the missing observations since the number of missing observations was rather small compared to the total data set.

Besides, we found out there was an extra district 79, New York City’s Alternative Schools District, included in the data set. Since it was not the focus of our research, we decided to drop the observations of District 79 to avoid the influence.

(i) Heatmap of the Graduation Rate among Districts

graduate_per$District <- factor(graduate_per$District)     

ggplot(graduate_per, aes(Cohort_Year, District, fill = sum_per_grad)) + 
    geom_tile() +
   # geom_text(aes(label =round(sum_per_grad,3)), color = "white",size=3) +
    scale_x_continuous(breaks = seq(2001, 2012, 1))+
    theme(axis.text.x = element_text(angle=10))+
    scale_fill_viridis()+
    labs(title = "The graduation rate of different districts from 2001 to 2012",x="Cohort Year", fill="Graduation Rate")

After the process of data cleansing, we attempted to demonstrate the graduation rates of all students among the 32 districts. According to the dataset, the cohort consists of all students who first entered 9th grade in a given school year (e.g. the Cohort of 2006 entered 9th grade in the 2006-2007 school year). Graduates are defined as those students earning either a Local or Regents diploma. From the heatmap, we found out that the two districts with the best graduation rate were District 26 and District 13, and the districts with the decent graduation rates were 28, 22 and 4. On the other hand, the graduation rate of District 23, 16 and 8 was the lowest, especially District 23 where the rate was decreasing after 2004 while the rate of other districts was mostly gradually raising.

As we have known, District 23 is one of the smallest in the city, which serves Ocean Hill, Brownsville, and parts of East New York, and includes some of the city’s poorest neighborhoods. Single-family homes are interspersed with old brownstones, apartment buildings, large public housing projects and homeless shelters. The graduation rate shown by the graph seems to match with the education condition of the districts.

From the website (http://insideschools.org/districts/brooklyn/district-23), the schools, among the lowest-performing in the city, have been losing population, partly as a result of competition from charter schools. The Community Education Council voted in 2013 to do away with zoned schools, allowing parents to apply to any school in the district. However, parents complained that there were few viable choices.

(ii) Indicators of Districts with the Best and Worst Overall Graduation Rate

graduate_tidy<- graduate%>%
    group_by(District,Cohort_Year) %>% 
    dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                     sum_per_dropout= sum(num_dropout)/sum(num_cohort),
                     sum_per_regent=sum(num_regents) /sum(num_cohort),
                     sum_per_adregent= sum(num_adregents) /sum(num_cohort),
                     sum_per_wadregent= sum(num_wadregents)/sum(num_cohort),
                     sum_per_local = sum(num_local)/sum(num_cohort),
                     sum_per_sacc= sum(num_SACC)/sum(num_cohort),
                     sum_per_tasc= sum(num_TASC)/sum(num_cohort))
graduate_tidy$District <- factor(graduate_tidy$District)
orderclass <- graduate%>%
             group_by(District) %>% 
             dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort))
orderclass_best <- orderclass [order(-orderclass$sum_per_grad),][1:3,]
orderclass_worst <- orderclass [order(orderclass$sum_per_grad),][1:3,]
graduate_tidy1 <- within(graduate_tidy,{
  cat<-NA
  cat[District %in% orderclass_best$District ]<-"best"
  cat[District %in% orderclass_worst$District ]<-"worst"
  cat[is.na(cat)]<-"normal"
}
)
graduate_tidy1<-graduate_tidy1%>%filter(cat !='normal')
graduate_tidy1$cat <- factor(graduate_tidy1$cat, labels =  c("best","worst"))

After data preprocessing, there was another challenge of data processing we faced. We attempted to demonstrate the overall graduation rates of all districts over the years, but the number of districts was a bit too large for presentation. Thus, we tried to select the three districts with the best graduation rate and three with the worst one.

To attain this goal, we created a data frame called “orderclass” which contains the overall graduation rate grouped by district, then derive the three best and three worst records from that in order to add a new feature “cat” to the processed dataset with the purpose of indicating the category of the districts set up by ourselves.

graduate_tidy1$District<-factor(graduate_tidy1$District,levels=c(26,23,13,16,28,18))
to_string<-as_labeller(c('1'='district26','2'='district23','3'='district13','4'='district16','5'='district28','6'='district18'))
glabel<-c('Graduation Rate','Dropout Rate','Regent Rate','Advanced Regent Rate','Without Advanced Regent Rate','Local Rate','SACC Rate','TASC Rate')
ggparcoord(graduate_tidy1, columns =3:10,scale="globalminmax",groupColumn = "cat",alphaLines = 0.3)+theme(axis.text.x = element_text(size=10,angle=20))+
  scale_x_discrete(labels=glabel)+
  labs(title="Indicators of Six Districts with the Best and Worst Overall Graduation Rate ",col='Best/Worst') +
  facet_wrap(~District,scales='fixed',nrow=3,labeller=to_string)

We applied parallel coordinate to analyze the patterns of graduation indicators on districts with the best and the worst overall graduation rate. The multiple lines for each grid refer to the rates for each year.

For the districts with the best graduation rates, we found out that there was a similar pattern shared by the districts – they all got a relatively low dropout rate, low Local diploma percentage, low SACC percentage, low TASC percentage and high Regent percentage. Especially for District 26 and 13, they got a high rate of Advanced Regent Diploma and low rate of Regent without Advanced over the years.

For the three districts with the worst graduation rates, the dropout rate is relatively high and the Advanced Regent rate is relatively low. There were fluctuations existent over the indicators Regent rate, the rate of Regent without Advanced and Local rate among the years, especially for District 18, where we could see there were almost two patterns over the mentioned three indicators.

We would explain the meaning of the indicators related to graduation. New York State has selected a new high school equivalency test called the Test Assessing Secondary Completion (TASC) to replace the General Educational Development (GED) as the primary pathway to a New York State High School Equivalency Diploma effective January 2, 2014. The TASC is a secure, reliable and valid instrument that is used to verify that examinees have knowledge in core content areas equivalent to that of graduating high school seniors.

The Skills & Achievement Commencement Credential (SACC) is a certificate available only to students with severe cognitive disabilities who are eligible to take the NYSAA and have attended school for not less than 12 years, excluding Kindergarten. The Career Development and Occupational Studies (CDOS) Commencement Credential, which indicates that the student has the knowledge and skills necessary for entry-level employment.

In terms of the Local Diploma, all students can earn a Regents or Advanced Regents diploma; however, only students who meet specific criteria are eligible to graduate with a local diploma, which allows students to graduate with lower exam scores. Besides, an Advanced Regents diploma lets students demonstrate additional skills in math, science, and languages other than English.

b) Graduation Rate Analysis by English Level

graduate_ell<-read.csv("2016 Graduation_Rates_Public_District_ELL.csv",skip=8,col.names =col_names)
cols<-col_names[6:27]
graduate_ell[graduate_ell == "s"] = NA
graduate_ell[,cols] <- apply(graduate_ell[,cols], 2, function(x) as.numeric(x))

We imported the dataset of graduation indicators by English level, utilizing the techniques we used before including standardizing missing data and transferring the data type of features.

##remove the missing data in per_grads_cohort
graduate_ell <- graduate_ell[complete.cases(graduate_ell),]
graduate_ell <- graduate_ell%>% filter(District!=79)

We implemented the similar data preprocessing stated as above to prepare the data set for analysis. We figured out that a few observations are missing on all included variables. Therefore, we decided to remove all the missing observations, since the number of missing observations was rather small compared to the total data set.

Besides, we found out there was an extra district 79, New York City’s Alternative Schools District, included in the data set. Since it was not the focus of our research, we decided to drop the observations of District 79 to avoid the influence.

(i) Graduation Rate Analysis by English Level and District

graduate_ell_phist <- graduate_ell %>% 
  group_by(Category,Cohort_Year) %>% 
  dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort))
graduate_ell_per <- graduate_ell %>% 
  group_by(Category, District) %>% 
  dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                     sum_per_dropout= sum(num_dropout)/sum(num_cohort),
                     sum_per_regent=sum(num_regents) /sum(num_cohort),
                     sum_per_adregent= sum(num_adregents) /sum(num_cohort),
                     sum_per_wadregent= sum(num_wadregents)/sum(num_cohort),
                     sum_per_local = sum(num_local)/sum(num_cohort),
                     sum_per_sacc= sum(num_SACC)/sum(num_cohort),
                     sum_per_tasc= sum(num_TASC)/sum(num_cohort))
phist<- ggplot(graduate_ell_phist, aes(x =factor(Cohort_Year) , y = sum_per_grad, fill =Category)) +
    geom_bar(stat = "identity", position = "dodge") +
    labs(title = "Graduation Rate with respect to English Level", x = "Year", y = "Graduation Rate")
#grid.arrange(math_hist, math_pcp, nrow = 2)
 
pline<-  ggplot(graduate_ell_per , aes(x = District,  y = sum_per_grad, col = Category) )+
  geom_line()+
  scale_x_continuous(breaks = seq(1, 32, 1)) +
  ylim(0,1)+
  labs(title = "Graduation Rate with English Level and District", x = "District", y = "Graduation Rate")
grid.arrange(phist, pline, nrow = 2)

From the bar chart, it indicates the graduation rate with respect to English levels during the period from 2001 to 2012. In order to achieve this graph, we summarized the graduation rate grouped by category and cohort year. Over the years, the graduation rate for Former ELL was the best, while the rate for ELL was the worst. Besides, though the rate for English Proficient was in the middle, it was gradually increasing and approaching to the one for Former ELL.

From the line graph, it shows the overall graduation rate of three English levels among the 32 districts. In order to achieve this graph, we summarized the different graduation indicators grouped by category and district. The graduation rate pattern over the districts was shared by the three English levels generally. However, in the District 3, the rate for English Proficient was slightly better than the one for the Former ELL. Among all these districts, the graduation rates for District 13 were the best for all three English categories, while the graduation rates for District 8,16 and 23 were the worst for ELL, English Proficient, and Former ELL. There were also some special cases among districts. For instance, the difference in graduation rates between ELL and English Proficient was the largest in District 6, since the rate of English Proficient was close to that of Former ELL. However, the graduation rates of ELL and English Proficient was pretty close in District 18.

(ii) Graduation Indicators by English Levels

graduate_ell_tidy <- graduate_ell %>% 
  group_by(Category) %>% 
  dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                     sum_per_dropout= sum(num_dropout)/sum(num_cohort),
                     sum_per_regent=sum(num_regents) /sum(num_cohort),
                     sum_per_adregent= sum(num_adregents) /sum(num_cohort),
                     sum_per_wadregent= sum(num_wadregents)/sum(num_cohort),
                     sum_per_local = sum(num_local)/sum(num_cohort),
                     sum_per_sacc= sum(num_SACC)/sum(num_cohort),
                     sum_per_tasc= sum(num_TASC)/sum(num_cohort))
graduate_ell_tidy<-graduate_ell_tidy%>%gather(Indicator, Percentage, -Category,-sum_per_grad)
graduate_ell_tidy$Indicator<-factor(graduate_ell_tidy$Indicator,levels=c('sum_per_regent','sum_per_adregent','sum_per_wadregent','sum_per_dropout','sum_per_local','sum_per_sacc','sum_per_tasc'))

There was an another challenge we encountered while data analysis. We tried to facet wrap the indicator so as to show the different graduation rates with respect to English levels after summarizing the graduation rates grouped by category. However, the summarized graduation indicators were in wide forms, thus we had to transform them into the long format by using gather function.

to_string<-as_labeller(c('sum_per_adregent'='Advanced Regent Rate','sum_per_dropout'='Dropout Rate','sum_per_local'='Local Rate','sum_per_regent'='Regent Rate','sum_per_sacc'='SACC Rate','sum_per_tasc'='TASC Rate','sum_per_wadregent'='Without Advanced Regent Rate'))
ggplot(graduate_ell_tidy, aes(x = Category, y = Percentage, fill=factor( Category))) +
  geom_bar(stat = "identity") +
  facet_wrap(~factor(Indicator),labeller=to_string) +
  labs(title = "Graduation Indicators by English Level", x = "English Level", y = "Indicator Precentage",fill="Category")+
  theme(axis.text.x = element_text(size=10,angle=20))

#  theme(legend.position = "bottom")+ 
# guides(fill=guide_legend(reverse=TRUE))

For dropout rate, ELL was highest, while Former ELL was lowest. For the indicators Regent rate and Without Advanced Regent Rate, Former ELL was the best, then was English Proficient, while ELL was the worst. However, for the Advanced Regent rate, English Proficient was slightly better than the Former ELL. Besides, there were fewer individuals of English Proficient type getting Local Diplomas(allowed to graduate with fewer exam scores)

Therefore, we could conclude that Former ELL performs better for the general graduation rates, while the English Proficient performs better for the advanced levels, which means more students of English Proficient earned high exam scores among the graduate students. And the students as English learners ranked last in various dimensions.

c) Graduation Rate Analysis by Gender

graduate_gen<-read.csv("2016 Graduation_Rates_Public_District_Gender.csv",skip=8,col.names =col_names)
cols<-col_names[6:27]
graduate_gen[graduate_gen == "s"] = NA
graduate_gen[,cols] <- apply(graduate_gen[,cols], 2, function(x) as.numeric(x))

We imported the dataset of graduation indicators by gender, utilizing the techniques we used before including standardizing missing data and transferring the data type of features.

##remove the missing data in per_grads_cohort
graduate_gen <- graduate_gen[complete.cases(graduate_gen),]
graduate_gen <- graduate_gen%>% filter(District!=79)

We implemented the similar data preprocessing stated as above to prepare the data set for analysis. We found out that a few observations were missing on all included variables. Therefore, we decided to remove all the missing observations, since the number of missing observations was rather small compared to the total data set.

Besides, we found out there was an extra district 79, New York City’s Alternative Schools District, included in the data set. Since it was not the focus of our research, we decided to drop the observations of District 79 to avoid the influence.

(i) Graduation Rate Analysis by Gender,District and Year

graduate_gen_phist <- graduate_gen %>% 
  group_by(Category,Cohort_Year) %>% 
  dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort))
graduate_gen_per <- graduate_gen %>% 
  group_by(Category, District) %>% 
  dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                     sum_per_dropout= sum(num_dropout)/sum(num_cohort),
                     sum_per_regent=sum(num_regents) /sum(num_cohort),
                     sum_per_adregent= sum(num_adregents) /sum(num_cohort),
                     sum_per_wadregent= sum(num_wadregents)/sum(num_cohort),
                     sum_per_local = sum(num_local)/sum(num_cohort),
                     sum_per_sacc= sum(num_SACC)/sum(num_cohort),
                     sum_per_tasc= sum(num_TASC)/sum(num_cohort))
phist<- ggplot(graduate_gen_phist, aes(x =factor(Cohort_Year) , y = sum_per_grad, fill =Category)) +
    geom_bar(stat = "identity", position = "dodge") +
    labs(title = "Graduation Rate with respect to Gender over the years", x = "Year", y = "Graduation Rate")
#grid.arrange(math_hist, math_pcp, nrow = 2)
 
pline<-  ggplot(graduate_gen_per , aes(x = District,  y = sum_per_grad, col = Category) )+
  geom_line()+
  scale_x_continuous(breaks = seq(1, 32, 1)) +
  ylim(0,1)+
  labs(title = "Graduation Rate with Gender and District", x = "District", y = "Graduation Rate")
grid.arrange(phist, pline, nrow = 2)

In order to achieve this bar chart, we summarized the graduation rate grouped by gender and cohort year. From the bar chart, we have known that over the years, the graduation rate of females was better than the one of the males. The rates of both males and females showed an upward trend from 2001 to 2012.

In order to achieve the line graph, we summarized the different graduation indicators grouped by gender and district. According to the line graph, the District 13,12 and 32 had the least disparity of graduation rates between males and females, which means the male and female students perform very similar in these three districts.

(ii) Graduation Indicators by Gender

graduate_gen_tidy <- graduate_gen %>% 
  group_by(Category) %>% 
  dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                     sum_per_dropout= sum(num_dropout)/sum(num_cohort),
                     sum_per_regent=sum(num_regents) /sum(num_cohort),
                     sum_per_adregent= sum(num_adregents) /sum(num_cohort),
                     sum_per_wadregent= sum(num_wadregents)/sum(num_cohort),
                     sum_per_local = sum(num_local)/sum(num_cohort),
                     sum_per_sacc= sum(num_SACC)/sum(num_cohort),
                     sum_per_tasc= sum(num_TASC)/sum(num_cohort))
graduate_geb_tidy<-graduate_gen_tidy%>%gather(Indicator, Percentage, -Category,-sum_per_grad)
graduate_geb_tidy$Indicator<-factor(graduate_geb_tidy$Indicator,levels=c('sum_per_regent','sum_per_adregent','sum_per_wadregent','sum_per_dropout','sum_per_local','sum_per_sacc','sum_per_tasc'))

We tried to facet wrap the graduation indicator so as to show the different graduation rates with respect to gender after summarizing the graduation rates grouped by category. However, the summarized graduation indicators were in wide forms, thus we had to transform them into the long format by using gather function.

to_string<-as_labeller(c('sum_per_adregent'='Advanced Regent Rate','sum_per_dropout'='Dropout Rate','sum_per_local'='Local Rate','sum_per_regent'='Regent Rate','sum_per_sacc'='SACC Rate','sum_per_tasc'='TASC Rate','sum_per_wadregent'='Without Advanced Regent Rate'))
ggplot(graduate_geb_tidy, aes(x = Category, y = Percentage, fill=Category)) +
  geom_bar(stat = "identity") +
  facet_wrap(~factor(Indicator),labeller=to_string) +
  labs(title = "Various Graduation Indicators by Gender", x = "Gender", y = "Indicator Score",col="Category")+
  theme(axis.text.x = element_text(size=10,angle=0))

#  theme(legend.position = "bottom")+ 
# guides(fill=guide_legend(reverse=TRUE))

From the graph above, we noticed that no matter for Regent rates, or Advanced Regent rates or Without Advanced Regents rates, females had an edge over males. For the dropput rate, the rate belonged to females was lower. Nevertheless, in terms of the local rate, the rate of females was slightly bigger than the one of the males.

In conclusion, females perform better than males for most of the graduation indicators, in different districts during the period from 2001 to 2012.

d)Graduation Rate Analysis by Ethinicity

graduate_eth<-read.csv("2016 Graduation_Rates_Public_District_Ethnicity.csv",skip=8,col.names =col_names)
cols<-col_names[6:27]
graduate_eth[graduate_eth == "s"] = NA
graduate_eth[,cols] <- apply(graduate_eth[,cols], 2, function(x) as.numeric(x))

We imported the dataset of graduation indicators by ethnicity, utilizing the techniques we used before including standardizing missing data and transferring the data type of features.

##remove the missing data in per_grads_cohort
graduate_eth<- graduate_eth[complete.cases(graduate_eth),]
graduate_eth <- graduate_eth%>% filter(District!=79)

We implemented the similar data preprocessing stated as above to prepare the data set for analysis. We found out that a few observations are missing on all included variables. Therefore, we decided to remove all the missing observations, since the number of missing observations was rather small compared to the total data set.

Besides, we found out there was an extra district 79, New York City’s Alternative Schools District, included in the data set. Since it was not the focus of our research, we decided to drop the observations of District 79 to avoid the influence.

(i) Graduation Rate Analysis by Ethnicity,District and Year

graduate_eth_heat<- graduate_eth %>%
    group_by(District,Category) %>% 
   # dplyr::summarise(num_grads= sum(num_cohort))
     dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort))
graduate_eth_heat$District <- factor(graduate_eth_heat$District)     
ggplot(graduate_eth_heat, aes(Category,District,fill = sum_per_grad)) + 
    geom_tile() +
   # geom_text(aes(label =round(sum_per_grad,3)), color = "white",size=3) +
    theme(axis.text.x = element_text(angle=0))+
    scale_fill_viridis()+
    labs(title = "The Graduation Rate of Different Ethnicities in Districts",fill="Graduation Rate")

At first, we tried to demonstrate the graduation rate of different ethnicities in districts using a line graph or histogram, but we figured out that the number of categories was too large to explicitly show the differences. Therefore, we decided to utilize heatmap to indicate the graduation rate differences with respect to districts and ethnicities.

From the heatmap above, we found out that there were some missing data for Asian in District 16, Multi-Racial and Native American in a few districts. It demonstrates that Asian and Native American performed the best over the districts, while Native American got the lowest graduation rate especially for District 16 and District 7.

For the Asian group, districts 13, 10, 5 and 4 got the best graduation rate, while districts 23 and 18 got the worst rate.

In terms of the Multi-Racial group, they got the best rate in districts 29, 21, 13, 4 and 3, while they got the worst one in District 27.

For the white group, the graduation rate difference over the districts was the most obvious among the ethnicity groups, with the best ones in District 13 and District 3, and the worst ones in District 23 and District 16.

graduate_eth_line<- graduate_eth %>%
    group_by(Cohort_Year,Category) %>% 
   # dplyr::summarise(num_grads= sum(num_cohort))
     dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort))
ggplot(graduate_eth_line , aes(x = Cohort_Year,  y = sum_per_grad, col = Category) )+
  geom_line(size=0.8)+
  scale_x_continuous(breaks = seq(2001, 2012, 1))+
  scale_color_brewer(palette = "Set1")+
  ylim(0,1)+
  labs(title = "Graduation Rate with Ethnicity over Years", x = "Year", y = "Graduation Rate")

From the line graph, it indicates that students could be divided into two groups – the first group with relatively high rate includes Asian, White and Multi-Racial, while the second group with lower rate contains Black, Hispanic and Native American.

Over the years, the graduation rates of Asian, White, Black and Hispanic were increasing gradually. However, for Multi-Racial and Native American, there were a few fluctuations over the years. For Multi-Racial, the rate hit the lowest point in 2004 and 2009, while it reaches the peak in 2007 and 2010. As for Native American, 2004 witnessed the climax of the graduation rate.

(ii) Graduation Indicators by Ethnicity

graduate_eth_tidy <- graduate_eth %>% 
  group_by(Category) %>% 
  dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                     sum_per_dropout= sum(num_dropout)/sum(num_cohort),
                     sum_per_regent=sum(num_regents) /sum(num_cohort),
                     sum_per_adregent= sum(num_adregents) /sum(num_cohort),
                     sum_per_wadregent= sum(num_wadregents)/sum(num_cohort),
                     sum_per_local = sum(num_local)/sum(num_cohort),
                     sum_per_sacc= sum(num_SACC)/sum(num_cohort),
                     sum_per_tasc= sum(num_TASC)/sum(num_cohort))

Since the number of ethnicity categories was relatively large, we applied the parallel coordinate instead of histogram and facet wrap to analyze the graduation indicators by ethnicity.

glabel<-c('Graduation Rate','Dropout Rate','Regent Rate','Advanced Regent Rate','Without Advanced Regent Rate','Local Rate','SACC Rate','TASC Rate')
ggparcoord(graduate_eth_tidy , columns =2:9,scale="globalminmax",groupColumn = "Category")+
  theme(axis.text.x = element_text(size=10,angle=10))+
  scale_x_discrete(labels=glabel)+
  scale_color_brewer(palette = "Set1")+
  ggtitle("Graduation Indicators by Ethnicity ")

For Asian, Multi-Racial and White, they got relatively high graduation rate (over 80%) and low dropout rate(about 10%). For the category Asian, majority of the graduate students got Regent rate, where the Advanced Regent rate was higher than the Without Advanced Regent rate. In terms of Multi-Racial and White students, the students got higher Without Advanced Regent rate compared to Advanced Regent rate.

For the other three groups Black, Hispanic and Native American, the students earned relatively low graduation rate (about 60%), relatively high dropout rate (about 20%) and low Regent rate (about 50%), most of which were belonged to Without Advanced Regent Diploma.

e) Graduation Rate Analysis by SWD

graduate_swd<-read.csv("2016 Graduation_Rates_Public_District_SWD.csv",skip=8,col.names =col_names)
cols<-col_names[6:27]
graduate_swd[graduate_swd == "s"] = NA
graduate_swd[,cols] <- apply(graduate_swd[,cols], 2, function(x) as.numeric(x))

We imported the dataset of graduation indicators by SWD, utilizing the techniques we used before including standardizing missing data and transferring the data type of features.

##remove the missing data in per_grads_cohort
graduate_swd<- graduate_swd[complete.cases(graduate_swd),]
graduate_swd <- graduate_swd%>% filter(District!=79)

We implemented the similar data preprocessing stated as above to prepare the data set for analysis. We found out that a few observations are missing on all included variables. Therefore, we decided to remove all the missing observations, since the number of missing observations was rather small compared to the total data set.

Besides, we found out there was an extra district 79, New York City’s Alternative Schools District, included in the data set. Since it was not the focus of our research, we decided to drop the observations of District 79 to avoid the influence.

graduate_swd_heat<- graduate_swd %>%
    group_by(District,Category) %>% 
   # dplyr::summarise(num_grads= sum(num_cohort))
     dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                      sum_per_sacc= sum(num_SACC)/sum(num_cohort))
graduate_swd_heat$District <- factor(graduate_swd_heat$District)     
p1<-ggplot(graduate_swd_heat, aes(Category,District,fill = sum_per_grad)) + 
    geom_tile() +
   # geom_text(aes(label =round(sum_per_grad,3)), color = "white",size=3) +
   # theme(axis.text.x = element_text(angle=10))+
    scale_fill_viridis()+
    labs(title = "The graduation rate by swd in districts",fill="Graduation Rate")
p2<-ggplot(graduate_swd_heat, aes(Category,District,fill = sum_per_sacc)) + 
    geom_tile() +
   # geom_text(aes(label =round(sum_per_sacc,3)), color = "white",size=3) +
   # theme(axis.text.x = element_text(angle=10))+
    scale_fill_viridis()+
    labs(title = "The SACC rate by swd in districts",fill="SACC Rate")
grid.arrange(p1,p2,nrow=1)

SWD means Student with a Disability. Since SACC Certificate (certificate for students with disabilities) was strongly related to the disabled students, we drew two heatmaps for comparison – one is the graduation rate by SWD in districts, and the other is SACC rate with respect to SWD in districts.

From the heatmaps above, we attempted to show the graduation rate and SACC rate with respect to SWD. In terms of the graduation rate, the students without disability perform better than the ones with disability among the districts. As for the SACC rate, District 16 had the largest percentage of students with disability who got the SACC Certificate (certificate for students with disabilities).

(i) Graduation Indicators by SWD

graduate_swd_line<- graduate_swd %>%
    group_by(Cohort_Year,Category) %>% 
   # dplyr::summarise(num_grads= sum(num_cohort))
    dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort),
                     sum_per_dropout= sum(num_dropout)/sum(num_cohort),
                     sum_per_regent=sum(num_regents) /sum(num_cohort),
                     sum_per_sacc= sum(num_SACC)/sum(num_cohort))%>%
     gather(Indicator, Percentage, -Category,-Cohort_Year)
#graduate_swd_line$Indicator<-factor(graduate_swd_line$Indicator,levels=c('Graduation Rate','Dropout Rate','Regent Rate','SACC Rate'))
ggplot(graduate_swd_line , aes(x = Cohort_Year,  y = Percentage, col = Indicator ) )+
  geom_line(aes(linetype=Category),size=0.8)+
  scale_x_continuous(breaks = seq(2001, 2012, 1)) +
  scale_color_brewer(palette = "Set1",labels=c('Dropout Rate','Graduation Rate','Regent Rate','SACC Rate'))+
  labs(title = "Graduation Rate with SWD and District", x = "Year", y = "Graduation Rate")

We would like to show the time series of different graduation indicators in regard to SWD category in a line graph, thus we applied gather function after summarizing the values of indicators and established the line graph setting color to indicator and line type to SWD category.

According to lines, the students without disability outperform SWD generally during the years. Over the years, the graduation rate and regent rate were getting better in both groups SWD and students without disability, especially for students without disability, the regent rate was approaching to graduation rate. We also noticed that the rate of SACC certificate was decreasing for students with disability.

f) SAT Analysis

SAT<-read.csv("SAT_Results.csv")
SAT[SAT=="s"]<-NA
SAT[,3:6] <- apply(SAT[,3:6], 2, function(x) as.numeric(x))
SAT <- SAT[complete.cases(SAT),]

We imported the dataset of SAT scores, utilizing the techniques we used before including standardizing missing data and transferring the data type of features.

(i) SAT Average Score Distribution of different schools

g1<-ggplot(data=na.omit(SAT))+
  geom_histogram(aes(x=as.numeric(as.character(SAT.Critical.Reading.Avg..Score))),binwidth = 5,fill="papayawhip", colour="khaki4")+
  xlab("SAT Critical Reading Avg. Score")+
  ggtitle("SAT Average Score Distribution of different schools")
g2<-ggplot(data=na.omit(SAT))+
  geom_histogram(aes(x=as.numeric(as.character(SAT.Math.Avg..Score))),binwidth = 5,fill="papayawhip", colour="khaki4")+
  xlab("SAT Math Avg. Score")
g3<-ggplot(data=na.omit(SAT))+
  geom_histogram(aes(x=as.numeric(as.character(SAT.Writing.Avg..Score ))),binwidth = 5,fill="papayawhip", colour="khaki4")+
  xlab("SAT Writing Avg. Score")
grid.arrange(g1,g2,g3,nrow=3)

The three histograms show the SAT average score of different schools, which are all right-skewed. In the plot of SAT Critical Reading Avg. Score, the majority of average score centered around the range [350,420]. On the other hand, the average score of math concentrated around 370, while the score of writing was around [350,400].

(ii) Proportion of SAT Takers over Cohort Students in 32 Districts

SAT_tidy<-SAT%>%mutate(District=substr(as.character(DBN),1,2))%>%select(District,Num.of.SAT.Test.Takers,SAT.Critical.Reading.Avg..Score,SAT.Math.Avg..Score,SAT.Writing.Avg..Score)
SAT_tidy$District<-as.factor(SAT_tidy$District)
SAT_tidy <- SAT_tidy%>% filter(District!=79 & District!=75)%>%
  mutate(sum_reading = Num.of.SAT.Test.Takers*SAT.Critical.Reading.Avg..Score, 
         sum_math = Num.of.SAT.Test.Takers*SAT.Math.Avg..Score,
         sum_writing = Num.of.SAT.Test.Takers*SAT.Writing.Avg..Score  )%>%
  group_by(District)%>% 
  dplyr::summarise(reading=sum(sum_reading)/sum(Num.of.SAT.Test.Takers),
                   math = sum(sum_math)/sum(Num.of.SAT.Test.Takers),
                   writing = sum(sum_writing)/sum(Num.of.SAT.Test.Takers),
                   num_taker =sum(Num.of.SAT.Test.Takers))%>%
                   gather(session,score,-District,-num_taker)
SAT_tidy$District <- as.numeric(SAT_tidy$District )
graduate_s<- graduate%>%
    group_by(District) %>% 
   # dplyr::summarise(num_grads= sum(num_cohort))
     dplyr::summarise(sum_per_grad= sum(num_grads)/sum(num_cohort), 
                      sum_cohort = sum(num_cohort))
grad_SAT<-merge(graduate_s,SAT_tidy,by="District")

In order to connect the SAT takers of different schools with the 32 districts, we extracted the District part from the DBN code of schools, creating new features “reading”,“math”,“writing” and “num_taker” to indicate the average score of takers in districts and the number of SAT takers in districts. Then we merged the processed SAT dataset with the dataset of graduation rates among districts. The reason why we got to transform the data type of the “District” feature to numeric in SAT_tidy was because the data type of the “District” feature in graduate_s data frame was numeric. In order to merge two data sets, we had to unify the data type of the feature.

Besides, we found out there were extra districts 75 and 79, included in the data set. Since the two districts were not the focus of our research, we decided to drop the observations of District 79 and District 75 to avoid the influence.

SAT_taker<-grad_SAT %>%mutate(per_taker = num_taker/sum_cohort)%>%select(District,per_taker)
SAT_taker<-unique(SAT_taker)
SAT_taker$District<-as.factor(SAT_taker$District)
ggplot(SAT_taker, aes(x = District, y = per_taker)) +
  geom_bar(stat = "identity",fill="papayawhip", colour="khaki4") +
  labs(title = "Percentage of SAT Takers over Cohort Students in 32 Districts", x = "District", y = "Percentage")+
  theme(axis.text.x = element_text(size=10,angle=0))

We utilized mutate function to calculate the percentage of students taking SAT in 32 districts.

The bar chart shows the proportion of the recorded SAT takers within the cohort students in 32 districts. It is worth mentioning that the percentage of SAT takers shown above just refers to the observations of the dataset, but not the real number of individuals taking SAT exams.

(iii) SAT Scores of Different Sessions with respect to District

SAT_tidy$District<-as.numeric(SAT_tidy$District)
SAT_tidy$session<-as.factor(SAT_tidy$session)
ggplot(SAT_tidy)+
  geom_line(aes(x = District,  y = score, col = session))+
  scale_x_continuous(breaks = seq(1, 32, 1)) +
  ylim(0,570)+
  labs(title = "SAT Scores of Different sessions with District", x = "District", y = "Scores")

According to the line graph, we found out that, among all the districts, the average math scores were highest than the reading scores and the writing scores. Besides, the average reading scores were slightly higher than the writing scores. The district with the best SAT scores was District 13, while the districts with the worst SAT scores were District 12 and District 32. In terms of the disparity among the scores of three sessions, District 20, 26 and 1 got the most evident disparity.

(iv) The Relationship between Graduation Rate and SAT Scores

ggplot(grad_SAT, aes(x=sum_per_grad, y=score)) + geom_point(aes(colour=session))+geom_smooth(aes(colour=session))+
  ylim(0,650)+
  labs(title = "The Relationship between Graduation Rate and SAT Scores", x = "graduatoin rate", y = "Scores")

According to the plot, it describes the correlation between graduation rate and SAT scores using both scatter plots and smooth lines.

From the slope of the graph, we found out that the SAT scores were slightly positively correlated with graduation rates, which means the higher graduation rate comes along with the higher SAT scores, especially for math scores.

(4) School Analysis

a) School Progress Evaluation

# clean
progress <- read.csv("progress.csv", header=TRUE, stringsAsFactors=FALSE)
progress[progress == "None"] = NA
progress[progress == "Pending"] = NA
progress <- na.omit(progress)
prog <- progress[c(1,4,5,6,7,8)]
colnames(prog) <- c("DB", "10-11","09-10","08-09","07-08","06-07")
prog <- prog %>% gather(Year, Rating, 2:6)
prog[prog == "A"] = 4
prog[prog == "B"] = 3
prog[prog == "C"] = 2
prog[prog == "D"] = 1
prog[prog == "F"] = 0
prog$Rating <- as.numeric(prog$Rating)
prog1 <- unique(prog %>% inner_join(loc))
Joining, by = "DB"
# plot
prog_D <- dplyr::summarize(group_by(prog1,Year,District), mean(Rating))
prog_D$District <- factor(prog_D$District)
colnames(prog_D)[3] <- "Rating"
ggplot(prog_D, aes(y = Year,x = District, fill=Rating)) + geom_raster() + labs(title = " School Progress Rating Mean by District ") + 
theme_grey(12)

Progress Reports graded each school with an A, B, C, D, or F and were based on student progress (60%), student performance (25%), and school environment (15%). Scores were based on comparing results from one school to a peer group of up to 40 schools with the most similar student population and to all schools citywide. They were designed to help parents, teachers, principals, and others understand how well schools are doing??and compare them to other, similar schools.

For the dataset of progress reports, we deleted missing data and meaningless data and changed the grade A-F to integer 4-0 to help the data visualization. Since the dataset provided the progress grades of all schools in NYC, we joined it with the data of location information and summrize them by district to get the average rating of each district. we tried to visualize it with parallel coordinates and heatmap and found that it was easier for us to get information and compare ratings between different districts intuitively with heatmap.

According to the figure above, we can find that the rating of all districts in 2008-2009 are remarkably higher than those in other years. This is weird beacause the rating are based on comparing with similar schools. The overall rating of all districts should not change a lot over the years. Therefore, We think there is something wrong with the data of 2008-2009. Without considering the data of 2008-2009, we can find that the progress ratings of district 2,20,26 were remarkably better than other that of those of other districts over the year, which means schools in these districts do better than schools in other districts.

b) School Quality Evaluation

# clean
quality <- read.csv("QualityReview.csv", header=TRUE, stringsAsFactors=FALSE)
colnames(quality) <- c("DBN", "Year", "Rating")
quality <- separate(quality, Year, c("x", "Year"), sep="Y")
quality <- quality[-2]
quality[quality == "U"] = 0
quality[quality == "UD"] = 0
quality[quality == "UPF"] = 1
quality[quality == "D"] = 2
quality[quality == "P"] = 3
quality[quality == "WD"] = 4
quality[quality == "O"] = 5
quality <- quality[-c(2994,3812),]
quality <- transform(quality, Rating = as.numeric(Rating))
quality[quality == " 11-12"] = "11-12"
# plot
qualityData2 <- unique(quality %>% inner_join(loc))
Joining, by = "DBN"
quality_D <- dplyr::summarize(group_by(qualityData2,Year,District), mean(Rating))
colnames(quality_D)[3] <- "Rating"
quality_D <- subset(quality_D,  ! District %in% c("0","75") )
quality_D$District <- factor(quality_D$District)
ggplot(quality_D, aes(y = Year,x = District, fill=Rating)) + geom_raster() + labs(title = " School Quality Rating Mean by District ") + 
theme_grey(16)

The Quality Review is a process that evaluates how well schools are organized to support student learning and teacher practice. It was developed to assist New York City Department of Education (NYCDOE) schools in raising student achievement by looking behind a school??s performance statistics to ensure that the school is engaged in effective methods of accelerating student learning.

For the quality review dataset, we removed the reduplicated data and changed the results, O, WD, P, etc. to integer, from 0 to 4 make it easier for us to visualize the data set. Since the dataset provided the quality grades of all schools in NYC, we joined it with the data of location information and summrize them by district to get the average rating of each district. Compared with parallel coordinates and histogram, heatmap could show the change of quality ratings over years explicitly and is convenient for us to compare the quality ratings between different districts.

From the figure, we can find that the overall rating of all districts were decreasing over these years. This could be resulted from that along with the development of society, people’s requirement level are increasing. Besides, we can find that the quality ratings of district 2,20,26 were remarkably better than other that of those of other districts over the year, which means schools in these districts are engaged in more effective methods of accelerating student learning. Combining the information from this figure with that from the above figure, we can conclude that schools in district 2,20,26 are good choice for parents and children.

(5) Further Analysis with social matters

a)Ethnicity Analysis and Policy

From the analysis of math score, ELA score, graduation rate and SAT score, we found out that Asian got the best performance while the performances of Hispanic, Black and native American were not that good, especially for native American.

According to the report Race, Ethnicity, and Education Policy, (https://scholar.harvard.edu/jlhochschild/publications/race-ethnicity-and-education-policy ) these outcomes result from a complex interaction of residential location, family socioeconomic status, personal preference, discrimination or biased treatment, and quality of schooling in the 32 districts (the major topic we research on). Educational attainment and race are clearly related, but not in any simple causal way.

Out of many proposals to tackle the problem of education disparity among ethnicity groups, school choice is the one mentioned and debated the most – whether to choose charter schools or privatized voucher programs. In fact, from the empirical research by Moe 2001, voucher programs have few implication on raising the students’ achievements. On the other hand, charter schools are more significant, since over a million students now attend them (out of 49 million students in K-12 schools). The number of charter schools is growing, and their structure and organization seem to be stabilizing. Some are lauded as the best hope for poor Black and Hispanic children, but others worry that charter schools openly, or implicitly reinforce racial stratification.

There are also some policies set up to decrease the education gap over the ethnicities. In order to make sure children of different groups to reach the similar academic level, NYC department of education(DOE) also implemented a policy called No Child Left Behind, (http://schools.nyc.gov/RulesPolicies/NCLB/default.htm ) where the DOE will provide schools identified by the state as Priority and Focus Schools with funding so they may offer other types of Expanded Learning Time (ELT) programs through the MTAC process. The education design results from the federal NCLB’s emphasis on schools’ “adequate yearly progress,” determined by standardized tests devised by each state. NCLB requires that, with a few exceptions, schools break out their performance by racial or ethnic subgroup, and show adequate yearly progress for each group.

b) Gender Analysis and Policy

From the plots we drew, we figured out that, in general, females slightly outperformed males no matter for the math scores or the ELA scores from 3 to 8 grades, or for the graduation rate in high school.

This conclusion actually matches with a lot of current researches which have found out that female students tend to perform better than male students, including to be more engaged with school, to get a better academic achievement, to less dropout and to get higher scores in reading, math, and science.

We believe there are two major reasons. The first one is related to nature and habit difference between males and females, for females are more goal-orientated and have more self-regulation, which fits well into the school lives. Another reason is relevant to the education policy and feminist movement, by which females are somehow getting a bit more attention than males. For instance, there also exists a “Respect for all “rule (http://schools.nyc.gov/RulesPolicies/RespectforAll/Commitment/default.htm) set by NYC department of education which states that “The NYCDOE is committed to maintaining a safe and supportive learning environment that is free from harassment, intimidation and/or bullying and from discrimination based on actual or perceived race, color, citizenship/immigration status, religion, creed, national origin, disability, ethnicity, gender, gender identity, gender expression, sexual orientation, or weight.”

Although females are more likely to outperform males in whether primary schools or high schools for math, reading, and writing. There is a research report “Better Test Scores Could Mean Trillions of Dollars for the U.S. Economy” (https://www.usnews.com/news/articles/2015/02/03/better-test-scores-could-mean-trillions-of-dollars-for-the-us-economy) which found out that females were more likely than boys, to have lower self-confidence in their math skills and more likely to feel anxious about applying math in the higher education field and even their careers.

For this problem, the effort by parents, schools, and policymakers is required to help both males and females realize their full potential in order to let them make a bigger contribution to the well – being of the society. For instance, to narrow the academic gap between males and females, schools could adjust their teaching methods like establishing special courses with more contents about wars and science fictions for male students. Moreover, to help female students realize their potential in math, NYC department of education could organize schools to held up workshops and seminars with a topic of math and science to arouse their interest in math and science.

c) SWD Analysis and Policy

From analysis above, it is apparent that due to the disability, students with disability perform remarkably worse than students without disability. The government and schools should pay more attention to students with disability to help them overcome obstacles of learning and get a better life.

d) English Language Learner(ELL) Analysis and policy

We can figure out the fact that from Grade 3 to 12, former ELLs performs much better than ELLs and similarly as the performance of EP(English Proficient). The fast improvements on ELLs’ academic performances may be caused by the supports of NYC Department of Education. NYC Department of Education prepares (NYCDOE)the Summer Enrichment Programs for English Language Learner(ELL). “ELLs in grades 2-8 can participate in math, science, and reading and writing activities during the summer. The DOE also offers summer learning opportunities for ELL students in high school who are on track to graduate.” (From DOE Official Website: http://schools.nyc.gov/Academics/ELL/default.htm) Moreover, NYCDOE also provide different kinds of ELLs for various help on their English study. “They offers three service delivery models: dual language (DL), transitional bilingual education (TBE), and English as a new language (ENL 11). These models are designed to promote proficiency in a student’s home language and English. Parents or guardians of ELLs are entitled to choose any of these service delivery models for their child regardless of whether their zoned school has their program of choice currently available.” (From DOE official report: http://schools.nyc.gov/NR/rdonlyres/0183D51C-377B-4ED7-BCBE-607AE4669D54/0/201415ELLDemographicReport.pdf )

e) The possible correlation on Income and students’ Academic performance

We hypothesized that the region with higher income may be with better students’ academic performances. So, we compared the map with graduation rate and income(http://www.businessinsider.com/new-york-city-income-maps-2014-12 ), and validated our hypothesis.

Apparently, darker places(with higher graduation, and with higher income) and lighter places of Graduation Rate and NYC Income match to each other.

f) School Analysis

From the visualization of school performance data, we could find that the performance of schools in District 2, 20 and 26 are remarkably better than those in other districts, which means that students in these districts can get more from school education and their learning is accelerated more efficiently. This could be a significant reason for better student performance in these two districts. Similarly, students perform worse in districts where school perform worse such as District 23.

Parents can send their children to districts where schools perform better than other districts to make their children study in better education environment and get better grade.
The government should pay more attention to districts where schools perform worse to make sure the equal access to education.

6. Conclusion

(1) Limitations

Although we dug deeply on our datasets, made insightful analyses in the K-12 education of NYC and constructed relationships between original data and social matters, our program still has some limitations. For the perspective of data, we cannot gather complete data from the year 2001 to 2016 in all aspects we analyzed. For example, when we discuss the graduation rate situation, the data from 2013 to 2016 is unavailable. This circumstance restricted our comprehensive comparison among all aspects over these years. For the perspective of analysis on the dataset, we always chose mean value as objects to compare, yet these methods may have biases in some situation. We expect to use more statistics to analyze the data in future. For the perspective of analyses with social matters, we compared and found the possible matters relevant to the phenomenon but cannot make sure the causal relationship. We could use causal inference knowledge to make our conclusion more valid. For the perspective of technique skills we used in this project, we utilized some efficient and accurate methods yet still have room to improve.

(2) Future direction:

In next step, we can contact the department of education of NYC to gather more complete data to improve our analysis. For the perspective of analysis on the dataset, we could analyze the scores meticulously, e.g. analyze the score of each grade respectively. Deeper insight into NYC K-12 data could be obtained by analyzing more relative data besides the income level, including the education levels of parents, the community environment, the crime rate, etc. , and research on their influence on student performance. Then we could read some relative papers to validate our conclusion drawn from data analysis. Furthermore, we can extend our K-12 education analysis to other cities in the States to find out the differences of K-12 education among different cities, then explore and generalize the influence factor of K-12 education. We can even extend the project to the whole world and compare the K-12 education of different countries all over the world. That would be a great and meaningful project then.

(3) Lesson Learned:

We learned a lot during our procedure of this project. Each of us tried to find two topics and related datasets at the beginning and we selected our most interesting topics after doing brief introductions for our ideas. This experience made us learn how to find a proper dataset and design a project at first. During our project, we meet twice a week to communicate our methods to plot, the quality of graphs and whether teammates’ graphs made sense. Gradually, we learned how to deal with messy data with skills of cleaning, transforming and loading and can choose the proper methods to plot and write data visualization R code efficiently. Moreover, we learned by ourselves on how to use D3 to plot the interactive map, indicating more information for the viewer. It enables us to do further more attractive and clear data analysis. In addition, during our analyses, we learned how to plot and read the graphs in simpler ways and how can we build correlations on social matters and our data to help decision makers to solve related matters. During our project, we studied both technique skills on visualization coding and data analyses, which build a solid foundation for our career path to data scientist.

LS0tCnRpdGxlOiAiTllDIEstMTIgRWR1Y2F0aW9uIEFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCiMgMS5JTlRST0RVQ1RJT04KCkVkdWNhdGlvbiBpcyBhbiBpbXBvcnRhbnQgcGFydCBvZiBzb2NpZXR5IHdoaWNoIGRpcmVjdGx5IGluZmx1ZW5jZXMgbWFua2luZCdzIGRldmVsb3BtZW50IGluIHRoZSBmdXR1cmUuIE5ldyBZb3JrIENpdHkgaXMgb25lIG9mIHRoZSBtb3N0IGFjdGl2ZSBjaXRpZXMgYWxsIG92ZXIgdGhlIHdvcmxkLCB3aGljaCBsb25ncyBmb3IgbW9yZSB0YWxlbnRzIGFuZCBleHBlY3RzIGJldHRlciBlZHVjYXRpb24gb24gY2l0aXplbnMuIFRodXMsIGluIG9yZGVyIHRvIGZpZ3VyZSBvdXQgdGhlIGVkdWNhdGlvbiBjb25kaXRpb24gaW4gTllDIGFuZCBnaXZlIHNvbWUgYWR2aWNlIHRvIHBvbGljeSBtYWtlcnMgYW5kIHN0dWRlbnRzIGFuZCB0aGVpciBwYXJlbnRzIG9uIHNjaG9vbCBzZWxlY3Rpb24gYW5kIHNlbGYtaW1wcm92ZW1lbnQsIHdlIGV4cGVjdCB0byBhbmFseXplIHNvbWUgbG9jYWwgc2Nob29sc+KAmSBhbmQgc3R1ZGVudHPigJkgZGF0YXNldHMuCgpXZSBjb25jZW50cmF0ZWQgb24gYW5hbHlzZXMgb2YgSy0xMiBhbmQgc2VuaW9yIGVkdWNhdGlvbi4gV2UgZGl2aWRlZCBvdXIgYXNzaWdubWVudCBpbnRvIHRocmVlIHBhcnQ6IDEpIFN0dWRlbnRz4oCZIGluZm9ybWF0aW9uIHZpc3VhbGl6YXRpb24gYW5kIGFuYWx5c2lzLiBUaGUgYW5hbHlzaXMgaXMgYmFzaWNhbGx5IG9uIHN0dWRlbnRz4oCZIGdyYWR1YXRpb24gcmF0ZXMsIG1hdGggYW5kIEVMQSBncmFkZXMsIFNBVCBzY29yZXMgYW5kIGVkdWNhdGVkIHJhdGUgd2l0aCByZXNwZWN0IHRvIGV0aG5pY2l0eSwgZ2VuZGVyLCBhbmQgRW5nbGlzaCBsYW5ndWFnZSBsZXZlbDsgMikgU2Nob29sc+KAmSBpbmZvcm1hdGlvbiB2aXN1YWxpemF0aW9uIGFuZCBhbmFseXNpcy4gSW4gdGhpcyBwYXJ0LCB3ZSBzcGVjaWZpY2FsbHkgc3R1ZHkgc2Nob29sc+KAmSByYXRpbmcgYW5kIHByb2dyZXNzIGNvbmRpdGlvbiBieSB5ZWFycyBhbmQgYXJlYXM7IDMpIEZ1cnRoZXIgYW5hbHlzaXMgYW5kIHN1Z2dlc3Rpb25zLiBCYXNlZCBvbiB0aGUgdmlzdWFsaXphdGlvbiBhbmQgYW5hbHlzaXMgY29tYmluaW5nIHdpdGggcG9saWNpZXMgYW5kIHNvY2lhbCBmYWN0b3JzLCB3ZSBjb3VsZCBnaXZlIHNvbWUgc3VnZ2VzdGlvbnMgZm9yIHBvbGljeSBtYWtlcnMgYW5kIGZvciBzdHVkZW50cyBhbmQgdGhlaXIgcGFyZW50cy4KCkV4aGlsYXJhdGVkIGJ5IG91ciBpZGVhLCB3ZSBsb29rZWQgZm9yIHRoZSBvcGVuIGRhdGFzZXQgb24gTllDIGFuZCBlZHVjYXRpb24gaW5mb3JtYXRpb24uIEZvcnR1bmF0ZWx5LCB0aGVyZSBhcmUgYSBsb3Qgb2YgZGF0YXNldCBmb3IgTllDIGFuZCB0aGUgb2ZmaWNpYWwgd2Vic2l0ZSBoZWxwcyB1cyBtdWNoLiBPdXIgZGF0YXNldHMgY2FtZSBmcm9tIHRoZSBOWUMgb3BlbiBkYXRhKGh0dHA6Ly9vcGVuZGF0YS5jaXR5b2ZuZXd5b3JrLnVzLykgYW5kIHRoZSBnb3Zlcm5tZW50IHdlYnNpdGUgb24gZWR1Y2F0aW9uIGRlcGFydG1lbnQgKGh0dHA6Ly9zY2hvb2xzLm55Yy5nb3YvZGVmYXVsdC5odG0pLiBGcm9tIE5ZQyBPcGVuIERhdGEsIHdlIGNvdWxkIGZpbmQgbWFueSBkYXRhc2V0cyBvbiBsb2NhbCBzY2hvb2xzIGluIEVkdWNhdGlvbiBzZWxlY3Rpb24gYmVsb3cuIFdlIHNlbGVjdGVkIHNvbWUgY3N2IGZvcm1hdCBkYXRhc2V0cyBvbiBzY2hvb2wgaW5mb3JtYXRpb24gZm9yIG91ciBhbmFseXNpcyBvYmplY3RzIGFuZCBnYWluZWQgc29tZSBnZW8taW5mb3JtYXRpb24gZm9yIGZ1cnRoZXIgbWFwIHZpc3VhbGl6YXRpb24uIEFuZCBpbiB0aGUgb2ZmaWNpYWwgd2Vic2l0ZSwgd2UgZmluYWxseSBzdXJwcmlzaW5nbHkgZm91bmQgdGhlIGNvbHVtbiBuYW1lZCDigJxQZXJmb3JtYW5jZSBhbmQgQWNjb3VudGFiaWxpdHnigJ0gb24gdGhlIGxlZnQgc2lkZSBvZiB0aGUgd2VicGFnZSwgYW5kIHRoZW4gZ2FpbmVkIHN0dWRlbnRz4oCZIHBlcmZvcm1hbmNlIGFuZCBncmFkdWF0aW9uIGluZm9ybWF0aW9uIGluIOKAnE5ZQyBkYXRh4oCdLiBUaGVzZSB0d28gd2Vic2l0ZXMgYXJlIHRoZSBzb3VyY2Ugb2Ygb3VyIGRhdGFzZXQuIEFuZCB3ZSBob3BlIHRoYXQgb3VyIGRhdGEgdmlzdWFsaXphdGlvbiBhbmQgYW5hbHlzaXMgY291bGQgaGVscCBwZW9wbGUgYSBsb3Qgb24gZWR1Y2F0aW9uIGRvbWFpbi4KCgojIDIuIFRFQU0KCk91ciBncm91cCBuYW1lLCBFREFzcXVhcmUsIHN0YW5kcyBmb3IgRWR1Y2F0aW9uIERhdGEgQW5hbHlzaXMgb24gRXhwbG9yZSBEYXRhIEFuYWx5c2lzLgpFREFzcXVhcmUgVGVhbSBtZW1iZXI6IFl1bnNpIFpoYW5nKHl6MzAxMiksIEt1bnlpIExpdShrbDI5MTIpLCBaZXl1IFllKHp5MjIzMikuCgpCYXNlZCBvbiB0aGUgZGl2aXNpb24gb2Ygb3VyIHByb2plY3QgYWJvdmUsIHdlIGhhZCBvdXIgb3duIHRhc2tzLiBZdW5zaSBhbmQgS3VueWkgd2VyZSByZXNwb25zaWJsZSBmb3IgdGhlIGZpcnN0IHBhcnQgYW5kIFpleXUgd2FzIHJlc3BvbnNpYmxlIGZvciB0aGUgc2Vjb25kIHBhcnQuIFRoZSBsYXN0IHBhcnQgd2FzIGNvbXBsZXRlZCBieSB1cyB0b2dldGhlci4KClNwZWNpZmljYWxseSwgWXVuc2kgdmlzdWFsaXplZCB0aGUgZGF0YSBvZiBzdHVkZW50c+KAmSBNYXRoIGFuZCBFTEEgZ3JhZGVzIHdpdGggaGlzdG9ncmFtLCBwYXJhbGxlbCBjb29yZGluYXRlLCBoZWF0bWFwIGFuZCBjb3ZhcmlhbmNlIG1hdHJpeCB0byBhbmFseXplIHN0dWRlbnRz4oCZIHBlcmZvcm1hbmNlIGluIGRpZmZlcmVudCBib3JvdWdocywgZ2VuZGVycywgYW5kIGV0aG5pY2l0eSBhbmQgZXhwbG9yZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTWF0aCBhbmQgRUxBIGdyYWRlcy4gS3VueWkgdXNlZCB0aGUgaGlzdG9ncmFtLCBoZWF0bWFwLCBzY2F0dGVyIHBsb3QgYW5kIHBhcmFsbGVsIGNvb3JkaW5hdGUgdG8gdmlzdWFsaXplIHRoZSBkYXRhIG9mIGdyYWR1YXRpb24gcmF0ZSBhbmQgU0FUIHNjb3JlcyBhbmQgYW5hbHl6ZWQgc3R1ZGVudHPigJkgcGVyZm9ybWFuY2Ugb2YgdGhlaXIgZ3JhZHVhdGlvbiB3aXRoIHJlc3BlY3QgdG8gZXRobmljaXR5LCBnZW5kZXIsIGFuZCBFbmdsaXNoIGxhbmd1YWdlIGxldmVsIHRvIGV4cGxvcmUgdGhlIGVmZmVjdHMgb2YgdGhlc2UgZmFjdG9ycyBvbiBzdHVkZW50c+KAmSBwZXJmb3JtYW5jZS4gRm9yIHRoZSBkYXRhIG9mIHNjaG9vbCBpbmZvcm1hdGlvbiwgWmV5dSB1c2VkIGhlYXRtYXAgYW5kIHBhcmFsbGVsIGNvb3JkaW5hdGVzIHBsb3QgYW5kIGhpc3RvZ3JhbSB0byB2aXN1YWxpemUgcXVhbGl0eSBhbmQgcHJvZ3Jlc3Mgb2Ygc2Nob29scyBmb3IgZGlmZmVyZW50IHllYXJzIGFuZCBib3JvdWdocyBhbmQgYW5hbHl6ZSB0aGUgY2hhbmdlIG9mIHRoZW0uIEJlc2lkZXMsIGhlIGFuYWx5emVkIHRoZSBwcm9wb3J0aW9uIG9mIHBlb3BsZSBlZHVjYXRlZCBpbiBOWUMgZm9yIGRpZmZlcmVudCBhZ2UgZ3JvdXAgKFNjaG9vbCBhZ2UoNS0xNykgYW5kIG92ZXIgNjUpIGZvciB5ZWFycy4gRnVydGhlcm1vcmUsIHdlIGJ1aWx0IGFuIGludGVyYWN0aXZlIG1hcCB0byBzaG93IG91ciB2aXN1YWxpemF0aW9uLgoKRm9yIHRoZSBsYXN0IHBhcnQsIHdlIGNvbW11bmljYXRlZCByZXN1bHRzIG9mIG91ciBvd24gdGFza3MgYW5kIGNvbWJpbmVkIHRoZW0gdG9nZXRoZXIgdG8gbG9vayBmb3IgbW9yZSBpbnNpZ2h0cyBpbnRvIHRoZXNlIGRhdGEuIFdpdGggY29sbGlzaW9uIHNwYXJrcyBvZiB3aXNkb20sIHdlIHByb3Bvc2VkIG5ldyB2aXN1YWxpemF0aW9ucyB0aGF0IGFyZSBsaWtlbHkgdG8gZ2l2ZSB1cyBzb21lIG90aGVyIGluc2lnaHRzIGludG8gb3VyIGRhdGEuIEFmdGVyIHdlIGZpZ3VyZWQgb3V0IHRoZSBlZHVjYXRpb24gY29uZGl0aW9uIGluIE5ZQywgd2UgZ2F2ZSBzb21lIHN1Z2dlc3Rpb25zIHRvIHBvbGljeSBtYWtlcnMsIHN0dWRlbnRzLCBhbmQgdGhlaXIgcGFyZW50cy4KCgojIDMuIEFOQUxZU0lTIG9mIERBVEEgUVVBTElUWQoKT3ZlcmFsbCwgdGhlIGRhdGFzZXRzIHF1aXRlIG1hdGNoZXMgb3VyIG5lZWRzIG9uIGFuYWx5emluZyBOWUMgSy0xMiBlZHVjYXRpb24uCgpIZXJlIGFyZSBzb21lIGNvbnMgb2Ygb3JpZ2luYWwgZGF0YXNldHMgYW5kIGNoYWxsZW5nZXMgd2Ugd2VyZSBmYWNlZCB3aGVuIHdlIGZpcnN0bHkgZ2FpbmVkIHRoZW0gZnJvbSB0aGUgb2ZmaWNhbCB3ZWJzaXRlIG9mIE5ldyBZb3JrIENpdHkgRGVwYXJ0bWVudCBvZiBFZHVjYXRpb24oTllDRE9FKS4KMS4gV2UgY291bGQgbm90IGdldCB0aGUgZGF0YSBvZiBncmFkdWF0aW9uIHJhdGUgaW4gMjAxMy0yMDE2IGFuZCB0aGUgTWF0aCBhbmQgRUxBIHNjb3JlIGluIDIwMDEtMjAwNiBhbmQgYmVjYXVzZSBpdCBpcyBub3QgcHJvdmlkZWQgb24gdGhlIHdlYnNpdGUgb2YgdGhlIGRlcGFydG1lbnQgb2YgZWR1Y2F0aW9uLiBUaGVyZWZvcmUsIHdlIGNhbm5vdCBhbmFseXplIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVtIGluIHRob3NlIHllYXJzLgoyLiBCZXNpZGVzLCB0aGVyZSBhcmUgc29tZSBtaXNzaW5nIGRhdGEgaW4gdGhlIGRhdGFzZXQsIHdoaWNoIG1ha2VzIHNvbWUgY2hhcnRzIGluY29tcGxldGUgYW5kIHdlIGNhbm5vdCB1c2UgdGhlbSBzdWNoIGFzIHBhcmFsbGVsIGNvb3JkaW5hdGUuCjMuIFRoZXJlIGFyZSBhbHNvIHNvbWUgcmVkdXBsaWNhdGVkIGRhdGEgdGhhdCB3ZSBuZWVkIHRvIGNsZWFuLgo0LiBUaGVyZSBhcmUgc29tZSB3cm9uZyBkYXRhIGluIHRoZSBkYXRhc2V0IG9mIGxvY2F0aW9uLCBpbmNsdWRpbmcgd3JvbmcgYm9yb3VnaCBhbmQgd3JvbmcgemlwIGNvZGUuCjUuIFdlIG5lZWQgdG8gY2hhbmdlIHRoZSBncmFkZSBBLCBCLCBDLCBEIHRvIGFuIGludGVnZXIgdG8gYnVpbGQgYSBjaGFydC4KCkRhdGEgUXVhbGl0eQpgYGB7cn0KbGlicmFyeShleHRyYWNhdCkKZ3JhZHVhdGVfZXRoX25hPC1ncmFkdWF0ZV9ldGhbY29sU3Vtcyhpcy5uYShncmFkdWF0ZV9ldGgpKT4wXQppbWFnZShtaXNzaW5nX2RhdGEuZnJhbWUoZ3JhZHVhdGVfZXRoX25hWyxdKSxjZXgubGFiID0gLjUpCmBgYAohW10obWlzc2luZy5wbmcpCkFsdGhvdWdoIHRoZSBkYXRhc2V0cyBhcmUgZGlydHksIHRoZXkgcHJvdmlkZWQgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgZWR1Y2F0aW9uIGFuZCBkaXZpZGVkIGRhdGEgaW50byBkaWZmZXJlbnQgZ3JvdXBzIG5hbWVseSB5ZWFyIGdyb3VwLCBkaXN0cmljdCwgRXRobmljaXR5LCBHZW5kZXIsIFNXRCwgIGFuZCBFTEwsIHdoaWNoIGVuYWJsZXMgdXMgdG8gZ2V0IGFuIGluc2lnaHQgaW50byBOWUMgSy0xMiBlZHVjYXRpb24gYW5kIHNhdmUgb3VyIHRpbWUgb2YgZGF0YSBwcm9jZXNzaW5nLgoKCiMgNC4gRVhFQ1VUSVZFIFNVTU1BUlkKCk91ciBwcm9qZWN0IGNvbmNlbnRyYXRlZCBvbiBhbmFseXNlcyBvZiBOWUMgSy0xMiBlZHVjYXRpb24uIFdlIGhhdmUgYnVpbHQgYW4gaW50ZXJhY3RpdmUgSGVhdG1hcCBvZiBOWUMgc2Nob29sIGRpc3RyaWN0IG9uIGEgd2ViIHRvIHNob3cgdGhlIGdyYWR1YXRpb24gcmF0ZSBvZiBkaWZmZXJlbnQgZGlzdHJpY3RzLiBXZSBmb3VuZCB0aGF0IGVkdWNhdGlvbiBsZXZlbHMgYW5kIHN0dWRlbnRzJyBwZXJmb3JtYW5jZXMgYXJlIHZhcmlvdXMgZnJvbSBkaWZmZXJlbnQgZGlzdHJpY3RzLCB3aGljaCBtYXkgcmVsYXRlZCB0byBzb21lIHNvY2lhbCBmYWN0b3JzIGRpc2N1c3NlZCBmb2xsb3dlZC4gCgpIZXJlIGlzIG91ciBpbnRlcmFjdGl2ZSBtYXAgbGluazogaHR0cHM6Ly9wbG5rci5jby9lZGl0L24zRDZoQ0VuaDJrZE5LOHBFZHltP3A9cHJldmlldwoKVGhlIGNvZGVzIGZvciBvdXIgaW50ZXJhY3RpdmUgbWFwIGFyZSBpbiBsZWZ0IGNvbHVtbnMuIFlvdSBjYW4gY2xpY2sgdGhlIHJpZ2h0LXRvcCBibHVlIGJ1dHRvbiB0byBsYXVuY2ggYSBwcmV2aWV3ZXIgdG8gYSBzZXBhcmF0ZSB3aW5kb3cgd2hpY2ggaXMgb3VyIHdlYnNpdGUgaW50ZXJmYWNlLiBUaGUgbGVmdCBwYXJ0IG9mIHRoZSB3ZWIgaXMgdGhlIG1hcCBvZiBOWUMgc2Nob29sIGRpc3RyaWN0cy4gVGhlIGRhcmtlciB0aGUgY29sb3Igb2YgYSBkaXN0cmljdCBpcywgdGhlIGhpZ2hlciB0aGUgZ3JhZHVhdGlvbiByYXRlIG9mIHRoaXMgZGlzdHJpY3QgaXMuIFRoZSByaWdodCBwYXJ0IG9mIHRoZSB3ZWIgaXMgdHdvIHN0YWNrZWQgYmFyIGNoYXJ0cyBzaG93aW5nIHRoZSBncmFkdWF0aW9uIHJlc3VsdHMgb2YgYSBjZXJ0YWluIGRpc3RyaWN0IG9mIGRpZmZlcmVudCB5ZWFycy4gVGhlIHRvcCBvbmUgc2hvd3MgdGhlIGNvbXBvc2l0aW9uIG9mIGNvaG9ydHMsIGluY2x1ZGluZyB0aGUgcmF0ZSBvZiBHcmFkdWF0aW9uLCBTdGlsbCBFbnJvbGxlZCwgRHJvcG91dCwgU2tpbGxzICYgQWNoaWV2ZW1lbnQgQ29tbWVuY2VtZW50IENyZWRlbnRpYWwgKFNBQ0MpIGFuZCBUZXN0IEFzc2Vzc2luZyBTZWNvbmRhcnkgQ29tcGxldGlvbiAoVEFTQykuIFRoZSBib3R0b20gb25lIHNob3dzIHRoZSBjb21wb3NpdGlvbiBvZiB0aGUgZ3JhZHVhdGlvbiwgaW5jbHVkaW5nIEFkdmFuY2VkIFJlZ2VudCwgUmVnZW50IHdpdGhvdXQgQWR2YW5jZWQgYW5kIExvY2FsLgoKW0EgQnJpZWYgSW5zdHJ1Y3Rpb24gZm9yIHRoZSBJbnRlcmFjdGl2ZSBNYXBdIFdoZW4geW91ciBtb3VzZSBob3ZlcnMgb24gYSBkaXN0cmljdCB0aGUgbWFwLCB0aGUgYmFzaWMgaW5mb3JtYXRpb24gb2YgdGhpcyBkaXN0cmljdCBpbiAyMDEyIGlzIHNob3duIGluIHRoZSBib3ggb24gdGhlIGxlZnQtdG9wIGNvcm5lciBvZiB0aGUgbWFwLiBXaGVuIGEgZGlzdHJpY3QgaXMgY2xpY2tlZCBvbiwgdGhlIHN0YWNrZWQgYmFyIGNoYXJ0cyB3aWxsIGNoYW5nZSB0byBzaG93IHRoZSBpbmZvcm1hdGlvbiBvZiB0aGlzIGRpc3RyaWN0LiBXaGVuIHlvdSBjbGljayBvbiB0aGUgbGVnZW5kIG9mIGEgZmVhdHVyZSBiZWxvdyBhIHN0YWNrZWQgYmFyIGNoYXJ0LCB0aGUgY2hhcnQgd2lsbCBjaGFuZ2UgYW5kIHNob3cgdGhlIHJlbWFpbmluZyBmZWF0dXJlcy4gQnkgdGhpcyB3YXksIHdlIGNhbiBjaG9vc2UgdGhlIHNwZWNpZmljIGZlYXR1cmUgd2UgYXJlIGludGVyZXN0ZWQgaW4gdG8gc2hvdyBpdCBpbiB0aGUgY2hhcnQuCgpXZSBwaWNrIHR3byBkaXN0cmljdHPigJkgZ3JhZHVhdGlvbiByZXN1bHQgYXMgYW4gZXhhbXBsZToKRm9yIERpc3RyaWN0IDI2ICh0aGUgc2NyZWVuc2hvdCBmb3IgZGlzdHJpY3QgMjYpOgohW10oZGlzdHJpY3QyNi5wbmcpCldpdGhpbiBhbGwgdGhlIGRpc3RyaWN0cywgRGlzdHJpY3QgMjYgaGF2ZSBnb3QgdGhlIG1vc3QgZXhjZWxsZW50IGdyYWR1YXRpb24gcGVyZm9ybWFuY2Ugb3ZlciB0aGUgeWVhcnMuIEFjY29yZGluZyB0byB0aGUgbWFwIHBhcnQgb2YgdGhlIGludGVyYWN0aXZlIGdyYXBoLCB0aGUgZGFya25lc3Mgb2YgRGlzdHJpY3QgMjYgcmFua3MgZmlyc3QsIHNpbmNlIHRoZSBncmFkdWF0aW9uIHJhdGUgb2YgdGhlIGRpc3RyaWN0IHdhcyA4NC43MSUgaW4gMjAxMiwgd2hpY2ggd2FzIHRoZSBoaWdoZXN0LgoKRnJvbSB0aGUgcmlnaHQgc2Vzc2lvbiBvZiB0aGUgZ3JhcGgsIHRoZSB0d28gc3RhY2tlZCBiYXIgY2hhcnRzIGRlbW9uc3RyYXRlIGJvdGggdGhlIGNvbXBvc2l0aW9uIG9mIGNvaG9ydCBhbmQgdGhlIGNvbXBvc2l0aW9uIG9mIGdyYWR1YXRpb24gc3R1ZGVudHMuIEluIHRoZSBjb21wb3NpdGlvbiBvZiBjb2hvcnRzLCB3ZSBmb3VuZCBvdXQgdGhhdCwgaW4gRGlzdHJpY3QgMjYsIHRoZSBncmFkdWF0aW9uIHJhdGVzIHdlcmUgYWxsIGFib3ZlIDcwJSwgZ3JhZHVhbGx5IHJhaXNpbmcgb3ZlciB0aGUgeWVhcnMsIHdoaWxlIHRoZSBkcm9wb3V0IHJhdGVzIHdlcmUgZ3JhZHVhbGx5IGRlY3JlYXNpbmcgdG8gbGVzcyB0aGFuIDUlLiBJbiB0aGUgZ3JhcGggb2YgdGhlIGNvbXBvc2l0aW9uIG9mIGdyYWR1YXRpb24sIHRoZSByYXRpbyBvZiB0aGUgc3R1ZGVudHMgd2l0aCByZWdlbnQgd2l0aG91dCBhZHZhbmNlZCBkaXBsb21hcyBoYWQgc2hvd24gYW4gdXB3YXJkIHRyZW5kLCByZWFjaGluZyB0byB0aGUgcGVyY2VudGFnZSBvdmVyIDUwJSBpbiAyMDEyLCB3aGVyZWFzIHRoZXJlIHdlcmUgZmV3ZXIgc3R1ZGVudHMgZ2V0dGluZyBsb2NhbCBkaXBsb21hcywgd2hpY2ggbWVhbnQgdGhlIGFjYWRlbWljIHBlcmZvcm1hbmNlIG9mIHRoZSBzdHVkZW50cyB3ZXJlIGdldHRpbmcgYmV0dGVyLiBCZXNpZGVzLCB0aGUgYWR2YW5jZWQgcmVnZW50IHJhdGUgcmVtYWluZWQgc2ltaWxhci4gCgpGb3IgRGlzdHJpY3QgMjMgKHRoZSBzY3JlZW5zaG90IGZvciBkaXN0cmljdCAyMykKIVtdKGRpc3RyaWN0MjMucG5nKQoKT3V0IG9mIGFsbCB0aGUgZGlzdHJpY3RzLCBEaXN0cmljdCAyMyBoYXZlIGdvdCB0aGUgbGVhc3QgZGVjZW50IGdyYWR1YXRpb24gcGVyZm9ybWFuY2Ugb3ZlciB0aGUgeWVhcnMuIEFjY29yZGluZyB0byB0aGUgbWFwIHBhcnQgb2YgdGhlIGludGVyYWN0aXZlIGdyYXBoLCB0aGUgY29sb3Igb2YgRGlzdHJpY3QgMjMgaXMgbGlnaHRlc3QsIHNpbmNlIHRoZSBncmFkdWF0aW9uIHJhdGUgb2YgdGhlIGRpc3RyaWN0IHdhcyBiZWxvdyA1MCUgaW4gMjAxMiwgd2hpY2ggd2FzIHRoZSBsb3dlc3QuCkZyb20gdGhlIHJpZ2h0IHNlc3Npb24gb2YgdGhlIGdyYXBoLCB0aGUgdHdvIHN0YWNrZWQgYmFyIGNoYXJ0cyBkZW1vbnN0cmF0ZSBib3RoIHRoZSBjb21wb3NpdGlvbiBvZiBjb2hvcnQgYW5kIHRoZSBjb21wb3NpdGlvbiBvZiBncmFkdWF0aW9uIHN0dWRlbnRzLiBJbiB0aGUgY29tcG9zaXRpb24gb2YgY29ob3J0cywgd2UgZm91bmQgb3V0IHRoYXQsIGluIERpc3RyaWN0IDIzLCB0aGUgZ3JhZHVhdGlvbiByYXRlcyB3ZXJlIGdlbmVyYWxseSBiZWxvdyA1MCUsIHJlYWNoaW5nIHRoZSBwZWFrIGluIDIwMDQsIHdoaWxlIHRoZSBzdGlsbCBlbnJvbGxlZCByYXRlcyB3ZXJlIGdyYWR1YWxseSBpbmNyZWFzaW5nIGFmdGVyIDIwMDYuIEluIHRoZSBncmFwaCBvZiB0aGUgY29tcG9zaXRpb24gb2YgZ3JhZHVhdGlvbiwgdGhlIHJhdGlvIG9mIHRoZSBzdHVkZW50cyB3aXRoIHJlZ2VudCB3aXRob3V0IGFkdmFuY2VkIGRpcGxvbWFzIGhhZCBzaG93biBhbiB1cHdhcmQgdHJlbmQsIHJlYWNoaW5nIHRvIHRoZSBwZXJjZW50YWdlIG92ZXIgNzAlIGluIDIwMTIsIHdoZXJlYXMgdGhlcmUgd2VyZSBmZXdlciBzdHVkZW50cyBnZXR0aW5nIGxvY2FsIGRpcGxvbWFzLiBIb3dldmVyLCB0aGUgQWR2YW5jZWQgUmVnZW50IHJhdGUgcmVtYWluZWQgYSByZWxhdGl2ZWx5IGxvdyBsZXZlbCAobGVzcyB0aGFuIDEwJSkgb3ZlciB0aGUgeWVhcnMuIAoKIyA1LiBNYWluIEFuYWx5c2lzCgojIyAoMSkgT3ZlcmFsbCBJbnNpZ2h0CgpOWUMgaXMgYSBjaXR5IHdpdGggcHJvc3Blcm91cyBlZHVjYXRpb24gZGV2ZWxvcG1lbnQsIHJhbmdpbmcgZnJvbSA1LTE3IHByaW1hcnkgZWR1Y2F0aW9uLCBoaWdoZXIgZWR1Y2F0aW9uIGFuZCBzZW5pb3IgZWR1Y2F0aW9uLiBIZXJlIHdlIGNvdWxkIHNlZSB0aGUgc3R1ZGVudCBwb3B1bGF0aW9uIHByb3BvcnRpb24gb2YgcGVvcGxlIGluIGFnZSA1LTE3IGFuZCBzZW5pb3IgcGVvcGxlIHRvIE5ZQyB0b3RhbCBwb3B1bGF0aW9uLgoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkodmlyaWRpcykKbGlicmFyeShncmlkKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShtaSkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGV4dHJhY2F0KQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHZjZCkKbGlicmFyeShHR2FsbHkpCmBgYAoKYGBge3J9CiNsb2FkIGRhdGEKbG9jIDwtIHJlYWQuY3N2KCJsb2NhdGlvbi5jc3YiLCBoZWFkZXI9VFJVRSwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKbG9jIDwtIGxvY1tjKDIsIDMsIDE1LCAxNywgMjMgKV0KY29sbmFtZXMobG9jKSA8LSBjKCJEQk4iLCAiREIiLCAiQm9yb3VnaCIsICJaaXBjb2RlIiwgIkRpc3RyaWN0IikKYGBgCgpgYGB7cn0KIyBjbGVhbgphZ2VzIDwtIHJlYWQuY3N2KCJBZ2UuY3N2IiwgaGVhZGVyPVRSVUUsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCkFnZTIgPC0gYWdlc1tjKDQsNiw4LDEwLDEyLDE0LDE2LDE4LDIwLDIyKV0KQWdlMSA8LSBhZ2VzW2MoMSwgMildCkFnZTIgPC0gZGF0YS5mcmFtZShsYXBwbHkoQWdlMiwgZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhzdWIoIiUiLCAiIiwgeCkpLzEwMCkgKSAKQWdlIDwtIGNiaW5kKEFnZTEsIEFnZTIpCkFnZVtBZ2UgPT0gIk5ZQyBUb3RhbCJdPSIgIE5ZQyBUb3RhbCIKY29sbmFtZXMoQWdlKSA8LSBjKCJBZ2UiLCAiQm9yb3VnaCIsICIxOTUwIiwgIjE5NjAiLCAiMTk3MCIsICIxOTgwIiwgIjE5OTAiLCAiMjAwMCIsICIyMDEwIiwgIjIwMjAiLCAiMjAzMCIsICIyMDQwIikKQWdlRGF0YSA8LSBBZ2VbYygxLDIsMyw0LDUsNiw3LDgsOSldCgojcGxvdAphZ2VfZiA8LSBBZ2VbMTo5XSAlPiUgZ2F0aGVyKFllYXIsIFBlcmNlbnQsMzo5KQphZ2VfZlthZ2VfZiA9PSAiU2Nob29sLUFnZSAoNSB0byAxNykiXSA9ICI1LTE3IgphZ2VfZlthZ2VfZiA9PSAiNjUgYW5kIG92ZXIiXSA9ICJvdmVyIDY1IgphZ2VfZiRZZWFyID0gYXMubnVtZXJpYyhhZ2VfZiRZZWFyKQpnZ3Bsb3QoYWdlX2YsIGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGNvbCA9IEJvcm91Z2gpKStnZW9tX2xpbmUoc2l6ZSA9IDAuNywgYWVzKGxpbmV0eXBlID0gQWdlKSkrc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTUwLCAyMDEwLCAxMCkpKwogIGxhYnModGl0bGUgPSAiIFBlcmNlbnQgb2YgVG90YWwgUG9wdWxhdGlvbiAxOTUwLTIwMTAiLCBsaW5ldHlwZSA9ICJBZ2UgR3JvdXAiKQpgYGAKQXQgZmlyc3QsIHdlIHVzZWQgdGhlIGhpc3RvZ3JhbSB0byBzaG93IHRoZSBwcm9wb3J0aW9uIG9mIGRpZmZlcmVudCB5ZWFycywgYnV0IGl0IGNhbm5vdCBzaG93IHRoZSB0cmVuZCBvZiB0aGUgcHJvcG9ydGlvbiBjaGFuZ2Ugb3ZlciB0aGVzZSB5ZWFycy4gVGhlcmVmb3JlLCB3ZSBjaG9zZSB0byB2aXN1YWxpemUgdGhlIGRhdGEgd2l0aCB0aW1lIHNlcmllcy4gQXBwYXJlbnRseSwgaXQgY2FuIGdpdmUgdXMgaW5zaWdodCBpbnRvIHRoZSBkYXRhLgoKClRoZSBmaWd1cmUgYWJvdmUgc2hvd3MgdGhlIGNoYW5nZSBvZiBwZXJjZW50IG9mIHRvdGFsIHBvcHVsYXRpb24gb2YgdHdvIGFnZSBncm91cHMsIDUtMTcgYW5kIG92ZXIgNjUsIGZyb20gMTk1MCB0byAyMDEwLgpGcm9tIHRoZSBmaWd1cmUsIHdlIGNvdWxkIGZpZ3VyZSBvdXQgdGhhdCBpbiBnZW5lcmFsLCB5b3VuZyBncm91cCdzIHBlcmNlbnQgaGFzIGJlZW4gZGVjcmVhc2luZyBvdmVyIHRoZXNlIHllYXJzLiBTcGVjaWZpY2FsbHksIHRoZSB5b3VuZydzIHBlcmNlbnQgcmVhY2hlZCBhIHBlYWsgaW4gMTk3MCBhbmQgMjAwMCwgd2hpY2ggaXMgY29uc2lzdGVudCB3aXRoIHRoZSBmYWN0IHRoYXQgdGhlIGdyb3d0aCByYXRlIHJlYWNoZWQgYSBwZWFrIGluIHRoZSAxOTcwcyBhbmQgMTk5MHMuICAgCihUaGlzIGluZm9ybWF0aW9uIGlzIGZyb20gdGhlIGRhdGEgaGVyZSBodHRwczovL3d3dy5nb29nbGUuY29tL3B1YmxpY2RhdGEvZXhwbG9yZT9kcz1kNWJuY3Bwam9mOGY5XyZtZXRfeT1zcF9wb3BfZ3JvdyZpZGltPWNvdW50cnklM0FVU0ElM0FJTkQlM0FDQU4maGw9ZW4mZGw9ZW4jIWN0eXBlPWwmc3RyYWlsPWZhbHNlJmJjcz1kJm5zZWxtPWgmbWV0X3k9c3BfcG9wX2dyb3cmc2NhbGVfeT1saW4maW5kX3k9ZmFsc2UmcmRpbT1yZWdpb24maWRpbT1jb3VudHJ5OlVTQSZpZmRpbT1yZWdpb24maGw9ZW5fVVMmZGw9ZW4maW5kPWZhbHNlKS4gIApBbmQgb2xkIGdyb3VwJ3MgcGVyY2VudCBoYXMgYmVlbiBpbmNyZWFzaW5nIG92ZXIgdGhlc2UgeWVhcnMsIHdoaWNoIGlzIGNvbnNpc3RlbnQgd2l0aCB0aGUgYWdlaW5nIG9mIHBvcHVsYXRpb24uCgpUaGVuIHdlIHVzZSB0aW1lLXNlcmllcyB0byBhbmFseXplIGZ1dHVyZSBlZHVjYXRpb24gY29uZGl0aW9uLgoKYGBge3J9CiNwcmVkaWN0aW9uCmFnZSA8LSBBZ2UgJT4lIGdhdGhlcihZZWFyLCBQZXJjZW50LDM6MTIpCmFnZVthZ2UgPT0gIlNjaG9vbC1BZ2UgKDUgdG8gMTcpIl0gPSAiNS0xNyIKYWdlW2FnZSA9PSAiNjUgYW5kIG92ZXIiXSA9ICJvdmVyIDY1IgphZ2UkWWVhciA9IGFzLm51bWVyaWMoYWdlJFllYXIpCmdncGxvdChhZ2UsIGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGNvbCA9IEJvcm91Z2gpKStnZW9tX2xpbmUoc2l6ZSA9IDAuNywgYWVzKGxpbmV0eXBlID0gQWdlKSkrc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxOTUwLCAyMDQwLCAxMCkpKwogIGxhYnModGl0bGUgPSAiIFBlcmNlbnQgb2YgVG90YWwgUG9wdWxhdGlvbiAxOTUwLTIwNDAiLCBsaW5ldHlwZSA9ICJBZ2UgR3JvdXAiKSArIAogIHRoZW1lX2dyZXkoMTYpCmBgYApJbiB0aGlzIGZpZ3VyZSwgZGF0YSBwcmVkaWN0ZWQgZnJvbSB0aGUgYWdlaW5nIG9mIHBvcHVsYXRpb24gaXMgYWRkZWQuIAoKIyMgKDIpIE1hdGggYW5kIEVMQSBTY29yZSBBbmFseXNpcyBpbiBHcmFkZSAzIH4gOCBmcm9tIDIwMDYgfiAyMDE2CiAKYGBge3J9CiNpbXBvcnQgbWF0aCBkYXRhc2V0CmNvbHVtbl9uYW1lID0gYygiRGlzdHJpY3QiLCAiR3JhZGUiLCAiWWVhciIsICJDYXRlZ29yeSIsICJOdW1iZXJfVGVzdGVkIiwgIk1lYW5fU2NhbGVfU2NvcmUiLCAibGV2ZWwxIiwgImxldmVsMV9wZXIiLCAibGV2ZWwyIiwgImxldmVsMl9wZXIiLCAibGV2ZWwzIiwgImxldmVsM19wZXIiLCAibGV2ZWw0IiwgImxldmVsNF9wZXIiLCAibGV2ZWwzJjQiLCAibGV2ZWwzJjRfcGVyIikKI2RhdGEgb2YgMjAxMy0yMDE2Cm1hdGhfYWxsX3N0dV8xMzE2IDwtIHJlYWQuY3N2KCJtYXRoX2FsbF9zdHUyMDEzLTIwMTYuY3N2Iiwgc2tpcCA9IDYsIGNvbC5uYW1lcyA9IGNvbHVtbl9uYW1lKQptYXRoX2V0aG5pY2l0eV8xMzE2IDwtIHJlYWQuY3N2KCJtYXRoX2V0aG5pY2l0eTEzLTE2LmNzdiIsIHNraXAgPSA2LCBjb2wubmFtZXMgPSBjb2x1bW5fbmFtZSkKbWF0aF9nZW5kZXJfMTMxNiA8LSByZWFkLmNzdigibWF0aF9nZW5kZXIxMy0xNi5jc3YiLCBza2lwID0gNiwgY29sLm5hbWVzID0gY29sdW1uX25hbWUpCm1hdGhfc3dkXzEzMTYgPC0gcmVhZC5jc3YoIm1hdGhfc3dkMTMtMTYuY3N2Iiwgc2tpcCA9IDYsIGNvbC5uYW1lcyA9IGNvbHVtbl9uYW1lKQptYXRoX2VsbF8xMzE2IDwtIHJlYWQuY3N2KCJtYXRoX2VsbDEzLTE2LmNzdiIsIHNraXAgPSA2LCBjb2wubmFtZXMgPSBjb2x1bW5fbmFtZSkKbWF0aF9hbGxfc3R1XzEzMTZbbWF0aF9hbGxfc3R1XzEzMTYgPT0gInMiXSA9IE5BCm1hdGhfZXRobmljaXR5XzEzMTZbbWF0aF9ldGhuaWNpdHlfMTMxNiA9PSAicyJdID0gTkEKbWF0aF9nZW5kZXJfMTMxNlttYXRoX2dlbmRlcl8xMzE2ID09ICJzIl0gPSBOQQptYXRoX3N3ZF8xMzE2W21hdGhfc3dkXzEzMTYgPT0gInMiXSA9IE5BCm1hdGhfZWxsXzEzMTZbbWF0aF9lbGxfMTMxNiA9PSAicyJdID0gTkEKCm1hdGhfYWxsX3N0dV8xMzE2JE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihtYXRoX2FsbF9zdHVfMTMxNiRNZWFuX1NjYWxlX1Njb3JlKSkKbWF0aF9ldGhuaWNpdHlfMTMxNiRNZWFuX1NjYWxlX1Njb3JlID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobWF0aF9ldGhuaWNpdHlfMTMxNiRNZWFuX1NjYWxlX1Njb3JlKSkKbWF0aF9nZW5kZXJfMTMxNiRNZWFuX1NjYWxlX1Njb3JlID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobWF0aF9nZW5kZXJfMTMxNiRNZWFuX1NjYWxlX1Njb3JlKSkKbWF0aF9zd2RfMTMxNiRNZWFuX1NjYWxlX1Njb3JlID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobWF0aF9zd2RfMTMxNiRNZWFuX1NjYWxlX1Njb3JlKSkKbWF0aF9lbGxfMTMxNiRNZWFuX1NjYWxlX1Njb3JlID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobWF0aF9lbGxfMTMxNiRNZWFuX1NjYWxlX1Njb3JlKSkKbWF0aF9lbGxfMTMxNiRsZXZlbDEgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihtYXRoX2VsbF8xMzE2JGxldmVsMSkpCm1hdGhfZWxsXzEzMTYkbGV2ZWwyID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobWF0aF9lbGxfMTMxNiRsZXZlbDIpKQptYXRoX2VsbF8xMzE2JGxldmVsMyA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKG1hdGhfZWxsXzEzMTYkbGV2ZWwzKSkKbWF0aF9lbGxfMTMxNiRsZXZlbDQgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihtYXRoX2VsbF8xMzE2JGxldmVsNCkpCgojZGF0YSBvZiAyMDA2LTIwMTIKbWF0aF9hbGxfc3R1XzA2MTIgPC0gcmVhZC5jc3YoIm1hdGhfYWxsX3N0dV8wNjEyLmNzdiIsIHNraXAgPSA2LCBjb2wubmFtZXMgPSBjb2x1bW5fbmFtZSkKbWF0aF9ldGhuaWNpdHlfMDYxMiA8LSByZWFkLmNzdigibWF0aF9ldGhuaWNpdHlfMDYxMi5jc3YiLCBza2lwID0gNiwgY29sLm5hbWVzID0gY29sdW1uX25hbWUpCm1hdGhfZ2VuZGVyXzA2MTIgPC0gcmVhZC5jc3YoIm1hdGhfZ2VuZGVyXzA2MTIuY3N2Iiwgc2tpcCA9IDYsIGNvbC5uYW1lcyA9IGNvbHVtbl9uYW1lKQptYXRoX3N3ZF8wNjEyIDwtIHJlYWQuY3N2KCJtYXRoX3N3ZDA2LTEyLmNzdiIsIHNraXAgPSA2LCBjb2wubmFtZXMgPSBjb2x1bW5fbmFtZSkKbWF0aF9lbGxfMDYxMiA8LSByZWFkLmNzdigibWF0aF9lbGwwNi0xMi5jc3YiLCBza2lwID0gNiwgY29sLm5hbWVzID0gY29sdW1uX25hbWUpCgoKbWF0aF9hbGxfc3R1XzA2MTJbbWF0aF9hbGxfc3R1XzA2MTIgPT0gInMiXSA9IE5BCm1hdGhfZXRobmljaXR5XzA2MTJbbWF0aF9ldGhuaWNpdHlfMDYxMiA9PSAicyJdID0gTkEKbWF0aF9nZW5kZXJfMDYxMlttYXRoX2dlbmRlcl8wNjEyID09ICJzIl0gPSBOQQptYXRoX3N3ZF8wNjEyW21hdGhfc3dkXzA2MTIgPT0gInMiXSA9IE5BCm1hdGhfZWxsXzA2MTJbbWF0aF9lbGxfMDYxMiA9PSAicyJdID0gTkEKbWF0aF9hbGxfc3R1XzA2MTIkTWVhbl9TY2FsZV9TY29yZSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKG1hdGhfYWxsX3N0dV8wNjEyJE1lYW5fU2NhbGVfU2NvcmUpKQptYXRoX2V0aG5pY2l0eV8wNjEyJE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihtYXRoX2V0aG5pY2l0eV8wNjEyJE1lYW5fU2NhbGVfU2NvcmUpKQptYXRoX2dlbmRlcl8wNjEyJE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihtYXRoX2dlbmRlcl8wNjEyJE1lYW5fU2NhbGVfU2NvcmUpKQptYXRoX3N3ZF8wNjEyJE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihtYXRoX3N3ZF8wNjEyJE1lYW5fU2NhbGVfU2NvcmUpKQptYXRoX2VsbF8wNjEyJE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihtYXRoX2VsbF8wNjEyJE1lYW5fU2NhbGVfU2NvcmUpKQoKbWF0aF9ldGhuaWNpdHlfMTMxNiA8LSBkYXRhLmZyYW1lKG1hdGhfZXRobmljaXR5XzEzMTYpCmBgYApIZXJlIHdlIHByb2Nlc3NlZCBvcmlnaW5hbCBNYXRoIHNjb3JlIGRhdGEuIER1cmluZyB0aGUgcHJvY2VzcyBvZiBpbnB1dCBtYXRoIGRhdGEsIHdlIHJlbW92ZWQgc2V2ZXJhbCB1c2VsZXNzIGxpbmVzIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNzdiwgYW5kIHJlc2V0IHRoZSBjb2x1bW4gbmFtZXMuIFRoZW4sIHdlIHNldCB0aGUgbWlzc2luZyBkYXRhLCB3aGljaCB3YXMgInMiIGluIHRoZSBvcmlnaW5hbCBkYXRhc2V0LCBhcyAiTkEicyBpbiBvcmRlciB0byBhdm9pZCBlcnJvcnMgaW4gZm9sbG93aW5nIGFuYWx5c2VzLiBOZXh0LCBJIHJlc2V0IHRoZSB0eXBlIG9mIGNvbHVtbnMgZm9yIGZ1cnRoZXIgYW5hbHlzaXMsIGkuZS4gd2Ugc2V0IHRoZSBjb2x1bW5zIHdpdGggbWlzc2luZyB2YWx1ZSBhcyBudW1lcmljICh3aGljaCBpcyBmYWN0b3IgYmVjYXVzZSBvZiAicyIpIHRvIGF2b2lkIG1pc3Rha2VzIGluIGZvbGxvd2luZyBudW1lcmljYWwgY2FsY3VsYXRpb24uIEFuZCBoZXJlIGlzIGEgdHJpY2sgdGhhdCB3aGVuIGNvbnZlcnRpbmcgdHlwZSBmYWN0b3IgdG8gdHlwZSBudW1lcmljLCB5b3UgaGF2ZSB0byBmaXJzdGx5IGNoYW5nZSBpdCB0byB0eXBlIGNoYXJhY3RlciB0aGVuIHR5cGUgbnVtZXJpYywgYmVjYXVzZSBSIHRyZWF0IHZhbHVlcyB3aXRoIHR5cGUgZmFjdG9yIGFzIGxhYmVscyBhbmQgaWdub3JlIHRoZSB2YWx1ZSBvZiBpdC4gSWYgeW91IHNldCBmYWN0b3IgYXMgbnVtZXJpYywgdGhlIG51bWVyaWMgdmFsdWUgaXMgcmFuZG9tLCB3aGljaCBpcyBub3QgYXBwcm9wcmlhdGUgdG8gb3VyIGFuYWx5c2VzLgpgYGB7cn0KIyNFTEEKI2ltcG9ydCBFTEEgZGF0YXNldApjb2x1bW5fbmFtZSA9IGMoIkRpc3RyaWN0IiwgIkdyYWRlIiwgIlllYXIiLCAiQ2F0ZWdvcnkiLCAiTnVtYmVyX1Rlc3RlZCIsICJNZWFuX1NjYWxlX1Njb3JlIiwgImxldmVsMSIsICJsZXZlbDFfcGVyIiwgImxldmVsMiIsICJsZXZlbDJfcGVyIiwgImxldmVsMyIsICJsZXZlbDNfcGVyIiwgImxldmVsNCIsICJsZXZlbDRfcGVyIiwgImxldmVsMyY0IiwgImxldmVsMyY0X3BlciIpCiNkYXRhIG9mIDIwMTMtMjAxNgplbGFfYWxsX3N0dV8xMzE2IDwtIHJlYWQuY3N2KCJlbGFfYWxsXzEzMTYuY3N2Iiwgc2tpcCA9IDYsIGNvbC5uYW1lcyA9IGNvbHVtbl9uYW1lKQplbGFfZXRobmljaXR5XzEzMTYgPC0gcmVhZC5jc3YoImVsYV9ldGhuaWNpdHlfMTMxNi5jc3YiLCBza2lwID0gNiwgY29sLm5hbWVzID0gY29sdW1uX25hbWUpCmVsYV9nZW5kZXJfMTMxNiA8LSByZWFkLmNzdigiZWxhX2dlbmRlcl8xMzE2LmNzdiIsIHNraXAgPSA2LCBjb2wubmFtZXMgPSBjb2x1bW5fbmFtZSkKZWxhX3N3ZF8xMzE2IDwtIHJlYWQuY3N2KCJlbGFfc3dkXzEzMTYuY3N2Iiwgc2tpcCA9IDYsIGNvbC5uYW1lcyA9IGNvbHVtbl9uYW1lKQplbGFfZWxsXzEzMTYgPC0gcmVhZC5jc3YoImVsYV9lbGxfMTMxNi5jc3YiLCBza2lwID0gNiwgY29sLm5hbWVzID0gY29sdW1uX25hbWUpCgplbGFfYWxsX3N0dV8xMzE2W2VsYV9hbGxfc3R1XzEzMTYgPT0gInMiXSA9IE5BCmVsYV9ldGhuaWNpdHlfMTMxNltlbGFfZXRobmljaXR5XzEzMTYgPT0gInMiXSA9IE5BCmVsYV9nZW5kZXJfMTMxNltlbGFfZ2VuZGVyXzEzMTYgPT0gInMiXSA9IE5BCmVsYV9zd2RfMTMxNltlbGFfc3dkXzEzMTYgPT0gInMiXSA9IE5BCmVsYV9lbGxfMTMxNltlbGFfZWxsXzEzMTYgPT0gInMiXSA9IE5BCgplbGFfYWxsX3N0dV8xMzE2JE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihlbGFfYWxsX3N0dV8xMzE2JE1lYW5fU2NhbGVfU2NvcmUpKQplbGFfZXRobmljaXR5XzEzMTYkTWVhbl9TY2FsZV9TY29yZSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGVsYV9ldGhuaWNpdHlfMTMxNiRNZWFuX1NjYWxlX1Njb3JlKSkKZWxhX2dlbmRlcl8xMzE2JE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihlbGFfZ2VuZGVyXzEzMTYkTWVhbl9TY2FsZV9TY29yZSkpCmVsYV9zd2RfMTMxNiRNZWFuX1NjYWxlX1Njb3JlID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZWxhX3N3ZF8xMzE2JE1lYW5fU2NhbGVfU2NvcmUpKQplbGFfZWxsXzEzMTYkTWVhbl9TY2FsZV9TY29yZSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGVsYV9lbGxfMTMxNiRNZWFuX1NjYWxlX1Njb3JlKSkKZWxhX2VsbF8xMzE2JGxldmVsMSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGVsYV9lbGxfMTMxNiRsZXZlbDEpKQplbGFfZWxsXzEzMTYkbGV2ZWwyID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZWxhX2VsbF8xMzE2JGxldmVsMikpCmVsYV9lbGxfMTMxNiRsZXZlbDMgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihlbGFfZWxsXzEzMTYkbGV2ZWwzKSkKZWxhX2VsbF8xMzE2JGxldmVsNCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGVsYV9lbGxfMTMxNiRsZXZlbDQpKQoKI2RhdGEgb2YgMjAwNi0yMDEyCmVsYV9hbGxfc3R1XzA2MTIgPC0gcmVhZC5jc3YoImVsYV9hbGxfMDYxMi5jc3YiLCBza2lwID0gNiwgY29sLm5hbWVzID0gY29sdW1uX25hbWUpCmVsYV9ldGhuaWNpdHlfMDYxMiA8LSByZWFkLmNzdigiZWxhX2V0aG5pY2l0eV8wNjEyLmNzdiIsIHNraXAgPSA2LCBjb2wubmFtZXMgPSBjb2x1bW5fbmFtZSkKZWxhX2dlbmRlcl8wNjEyIDwtIHJlYWQuY3N2KCJlbGFfZ2VuZGVyXzA2MTIuY3N2Iiwgc2tpcCA9IDYsIGNvbC5uYW1lcyA9IGNvbHVtbl9uYW1lKQplbGFfc3dkXzA2MTIgPC0gcmVhZC5jc3YoImVsYV9zd2RfMDYxMi5jc3YiLCBza2lwID0gNiwgY29sLm5hbWVzID0gY29sdW1uX25hbWUpCmVsYV9lbGxfMDYxMiA8LSByZWFkLmNzdigiZWxhX2VsbF8wNjEyLmNzdiIsIHNraXAgPSA2LCBjb2wubmFtZXMgPSBjb2x1bW5fbmFtZSkKCgplbGFfYWxsX3N0dV8wNjEyW2VsYV9hbGxfc3R1XzA2MTIgPT0gInMiXSA9IE5BCmVsYV9ldGhuaWNpdHlfMDYxMltlbGFfZXRobmljaXR5XzA2MTIgPT0gInMiXSA9IE5BCmVsYV9nZW5kZXJfMDYxMltlbGFfZ2VuZGVyXzA2MTIgPT0gInMiXSA9IE5BCmVsYV9zd2RfMDYxMltlbGFfc3dkXzA2MTIgPT0gInMiXSA9IE5BCmVsYV9lbGxfMDYxMltlbGFfZWxsXzA2MTIgPT0gInMiXSA9IE5BCmVsYV9hbGxfc3R1XzA2MTIkTWVhbl9TY2FsZV9TY29yZSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGVsYV9hbGxfc3R1XzA2MTIkTWVhbl9TY2FsZV9TY29yZSkpCmVsYV9ldGhuaWNpdHlfMDYxMiRNZWFuX1NjYWxlX1Njb3JlID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZWxhX2V0aG5pY2l0eV8wNjEyJE1lYW5fU2NhbGVfU2NvcmUpKQplbGFfZ2VuZGVyXzA2MTIkTWVhbl9TY2FsZV9TY29yZSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGVsYV9nZW5kZXJfMDYxMiRNZWFuX1NjYWxlX1Njb3JlKSkKZWxhX3N3ZF8wNjEyJE1lYW5fU2NhbGVfU2NvcmUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihlbGFfc3dkXzA2MTIkTWVhbl9TY2FsZV9TY29yZSkpCmVsYV9lbGxfMDYxMiRNZWFuX1NjYWxlX1Njb3JlID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoZWxhX2VsbF8wNjEyJE1lYW5fU2NhbGVfU2NvcmUpKQpgYGAKU2luY2UgRUxBIGRhdGEgaGFkIHRoZSBzYW1lIGRhdGEgc3RydWN0dXJlIGFzIE1hdGggZGF0YSwgaGVyZSB3ZSBkaWQgdGhlIHNpbWlsYXIgZGF0YSBwcm9jZXNzaW5nIGFzIGZvciBNYXRoIGRhdGEgZGVzY3JpYmVkIGJlZm9yZS4gSSByZW1vdmVkIHVzZWxlc3Mgcm93cyBhbmQgc2V0IGNvbHVtbiBuYW1lcyB3aGVuIGlucHV0aW5nIHRociBkYXRhLCBhbmQgdGhlbiBzZXQgInMiIGFzIE5Bcy4gRmluYWxseSB3ZSBhZGp1c3RlZCB0aGUgdHlwZSBvZiBkYXRhIGZvciBwcmVwYXJhdGlvbiBmb3IgZGF0YSBhbmFseXNlcy4KCgojIyMgYSkgSGVhdG1hcCBvbiBNYXRoIGFuZCBFTEEgc2NvcmUgYnkgZGlzdHJpY3QgMjAwNiB+IDIwMTYKYGBge3J9CiMgbWF0aCBzY29yZXMgb24gYWxsIHN0dWRlbnQKIyBUaGUgaGVhdG1hcCB3aXRoIGRpc3RyaWN0LCB5ZWFyLCBhbmQgZmlsbCBtZWFuIHNjb3JlIGZvciBtYXRoIG9uIHllYXIgMjAwNiB0byB5ZWFyIDIwMTYKbWF0aF9hbGxzdHUgPSByYmluZChtYXRoX2FsbF9zdHVfMDYxMiwgbWF0aF9hbGxfc3R1XzEzMTYpCmdncGxvdChtYXRoX2FsbHN0dSwgYWVzKHggPSBZZWFyLCB5ID0gRGlzdHJpY3QsIGZpbGwgPSBNZWFuX1NjYWxlX1Njb3JlKSkgKyAKICAgIGdlb21fdGlsZSgpICsKICAgIHNjYWxlX2ZpbGxfdmlyaWRpcygpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNiwgMjAxNiwgMSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMSwgMzIsIDEpKSArCiAgICBjb29yZF9mbGlwKCkgKwogICAgbGFicyh0aXRsZSA9ICJBbGwgc3R1ZGVudCBpbiBncmFkZXMgMyB+IDggTWF0aCBNZWFuIFNjb3JlIDIwMDYgfiAyMDE2IiwgeCA9ICJZZWFyIiwgeSA9ICJEaXN0cmljdCIpIApgYGAKVGhlIHJlYXNvbiB3ZSB1c2VkIGhlYXRtYXAgaGVyZSB3YXMgdGhhdCBoZWF0bWFwIGNvdWxkIGV4cGxpY2l0bHkgc2hvdyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHllYXJzIDIwMDYgfiAyMDEyIGFuZCB5ZWFycyAyMDEzIHRvIDIwMTYuIEJlY2F1c2UgdGhlIGRhdGEgY2FtZSBmcm9tIHR3byBkYXRhc2V0cywgd2UgdXNlZCAicmJpbmQiIHRvIGJpbmQgdGhlbSB0b2dldGhlciB0byBnYWluIGdlbmVyYWwgaW5mb3JtYXRpb24gb2YgM344IGdyYWRlIHN0dWRlbnQgbWF0aCBzY29yZXMgYnkgZGlzdHJpY3QgZnJvbSAyMDA2IH4gMjAxNi4gCgpUaGlzIHBsb3QgY2xlYXJseSBpbmRpY2F0ZXMgdGhhdCBzdHVkZW50cycgbWF0aCBzY29yZXMgc2lnbmlmaWNhbnRseSBkZWNyZWFzZWQgYWZ0ZXIgeWVhciAyMDEyLiBXZSBmaW5kIHRoZSBpbmZvcm1hdGlvbiBvbmxpbmUgKGh0dHA6Ly93d3cubnlkYWlseW5ld3MuY29tL25ldy15b3JrL2VkdWNhdGlvbi9jaXR5LXN0dWRlbnRzLXNjb3Jlcy1kcmFtYXRpYy1wbHVuZ2UtbmV3LXN0YW5kYXJkaXplZC10ZXN0cy1hcnRpY2xlLTEuMTQxOTk3MyApIHRvIGV4cGxhaW4gdGhpcyBwaGVub21lbm9uLiAiIE9ubHkgMzElIG9mIE5ldyBZb3JrIFN0YXRlIHN0dWRlbnRzIGluIGdyYWRlcyAzIHRvIDggcGFzc2VkIHRoZSAyMDEzIG1hdGggYW5kIHJlYWRpbmcgdGVzdHMsIGRvd24gZnJvbSA1NSUgaW4gRW5nbGlzaCBhbmQgNjUlIGluIG1hdGggaW4gMjAxMiBvbiBlYXNpZXIgdGVzdHMuIiBUaGlzIHJlcG9ydCByZXBvcnRlZCB0aGF0IHRoZSBzdWRkZW4gZHJvcCBvbiBtYXRoIHNjb3JlIGRpZCBub3QgcmVmbGVjdCBhIGRyb3AgaW4gcGVyZm9ybWFuY2UgYnV0IHJhdGhlciBhIHJhaXNpbmcgb2Ygc3RhbmRhcmRzIG9uIGV4YW1zLiBJbiBmYWN0LCAic3RhcnRpbmcgaW4gMjAxMywgdGhlIE5ZIFN0YXRlIEVkdWNhdGlvbiBEZXBhcnRtZW50IChOWVNFRCkgY2hhbmdlZCB0aGUgZXhhbXMgdG8gYmUgQ29tbW9uIENvcmUgYWxpZ25lZC4iKGNpdGluZyBmcm9tIGRhdGFzZXQgaW50cm9kdWN0aW9uKSBUaGlzIGZhY3QgaGFzIHZlcmlmaWVkIG91ciBkYXRhIGV4cGxvcmF0aW9uIG9uIG1hdGggbWVhbiBzY29yZXMgZnJvbSB5ZWFyIDIwMDYgdG8gMjAxNi4KYGBge3J9CiMgRUxBKEVuZ2xpc2ggTGFuZ3VhZ2UgQXJ0cykgc2NvcmVzIG9uIGFsbCBzdHVkZW50CiMgVGhlIGhlYXRtYXAgd2l0aCBkaXN0cmljdCwgeWVhciwgYW5kIGZpbGwgbWVhbiBzY29yZSBmb3IgbWF0aCBvbiB5ZWFyIDIwMDYgdG8geWVhciAyMDE2CmVsYV9hbGxzdHUgPSByYmluZChlbGFfYWxsX3N0dV8wNjEyLCBlbGFfYWxsX3N0dV8xMzE2KQpnZ3Bsb3QoZWxhX2FsbHN0dSwgYWVzKHggPSBZZWFyLCB5ID0gRGlzdHJpY3QsIGZpbGwgPSBNZWFuX1NjYWxlX1Njb3JlKSkgKyAKICAgIGdlb21fdGlsZSgpICsKICAgIHNjYWxlX2ZpbGxfdmlyaWRpcygpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNiwgMjAxNiwgMSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMSwgMzIsIDEpKSArCiAgICBjb29yZF9mbGlwKCkgKwogICAgbGFicyh0aXRsZSA9ICJBbGwgc3R1ZGVudCBpbiBncmFkZXMgMyB+IDggRUxBIE1lYW4gU2NvcmUgMjAwNiB+IDIwMTYiLCB4ID0gIlllYXIiLCB5ID0gIkRpc3RyaWN0IikgCmBgYApUaGlzIHBsb3QgaW5kaWNhdGVzIHRoYXQgdGhlIHJhaXNpbmcgc3RhbmRhcmRzIG9mIGV4YW1zIGxlZCB0byBtdWNoIGxvd2VyIGF2ZXJhZ2UgRUxBIHNjb3JlIGFzIHdlbGwuIFdlIGNvdWxkIHNlZSBib3RoIG1hdGggYW5kIEVMQSAoRW5nbGlzaCBMYW5ndWFnZSBBcnRzKSBzY29yZSBkZWNyZWFzZSBieSB0aGUgc2ltaWxhciBzY2FsZS4gCgoKIyMjICgyKSBDb21wYXJpc29uIG9mIHNjb3JlcyB3aXRoIGRpc3RyaWN0IGJ5IDIwMDYgfiAyMDEyIGFuZCAyMDEzIH4gMjAxNgpgYGB7cn0KIyBNYXRoCiMgU2VwZXJhdGUgTWF0aCBzY29yZXMgYnkgeWVhciAyMDA2IH4gMjAxMiBhbmQgMjAxMyB+IDIwMTYKcDA2MTIgPSBnZ3Bsb3QobWF0aF9hbGxfc3R1XzA2MTIsIGFlcyh4ID0gWWVhciwgeSA9IERpc3RyaWN0LCBmaWxsID0gTWVhbl9TY2FsZV9TY29yZSkpICsgCiAgICBnZW9tX3RpbGUoKSArCiAgICBzY2FsZV9maWxsX3ZpcmlkaXMoKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDYsIDIwMTYsIDEpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEsIDMyLCAxKSkgKwogICAgY29vcmRfZmxpcCgpICsKICAgIGxhYnModGl0bGUgPSAiQWxsIHN0dWRlbnQgTWF0aCBNZWFuIFNjb3JlIGJ5IERpc3RyaWN0IDIwMDYgfiAyMDEyIiwgeCA9ICJZZWFyIiwgeSA9ICJEaXN0cmljdCIpCgpwMTMxNiA9IGdncGxvdChtYXRoX2FsbF9zdHVfMTMxNiwgYWVzKHggPSBZZWFyLCB5ID0gRGlzdHJpY3QsIGZpbGwgPSBNZWFuX1NjYWxlX1Njb3JlKSkgKyAKICAgIGdlb21fdGlsZSgpICsKICAgIHNjYWxlX2ZpbGxfdmlyaWRpcygpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNiwgMjAxNiwgMSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMSwgMzIsIDEpKSArCiAgICBjb29yZF9mbGlwKCkgKwogICAgbGFicyh0aXRsZSA9ICJBbGwgc3R1ZGVudCBNYXRoIE1lYW4gU2NvcmUgYnkgRGlzdHJpY3QgMjAxMyB+IDIwMTYiLCB4ID0gIlllYXIiLCB5ID0gIkRpc3RyaWN0IikKCmdyaWQuYXJyYW5nZShwMDYxMiwgcDEzMTYsIG5yb3cgPSAyKQpgYGAKSGVyZSB3ZSBhbHNvIHVzZWQgaGVhdG1hcCB0byBjbGVhcmx5IHNob3cgdGhlIHBlcmZvcm1hbmNlIGRpZmZlcmVuY2VzIHdpdGhpbiBhbmQgYWNyb3NzIHllYXIgZ3JvdXBzIGFuZCBjb21wYXJlIHN0dWRlbnRzJyBwZXJmb3JtYW5jZSBieSBkaWZmZXJlbnQgZGlzdHJpY3RzLiAKCkFjY29yZGluZyB0byB0d28gZ3JhcGhzIGFib3ZlLCB3ZSBjYW4gaW5kaWNhdGUgdGhhdDoKMSkgQXMgdGltZSB3ZW50IGJ5LCBzdHVkZW50cycgcGVyZm9ybWFuY2VzIG9uIG1hdGggZXhhbSBiZWNhbWUgYmV0dGVyIHRoYW4gYmVmb3JlLiAKMikgQXMgdGhlIGRpZmZpY3VsdHkgb2YgbWF0aCBleGFtIGluY3JlYXNlZCBmcm9tIHllYXIgMjAwNiB+IDIwMTIgdG8gMjAxMyB+IDIwMTYsIHRoZSBwZXJmb3JtYW5jZSBkaWZmZXJlbmNlcyB3ZSBsYXJnZXIgdGhhbiBiZWZvcmUuCjMpIFRoZSBwcm9taW5lbnQgdHdvIGRpc3RyaWN0IHdlcmUgMjYgYW5kIDIsIHdoaWNoIG1pZ2h0IGNvcnJlc3BvbmQgdG8gc29tZSBzb2NpYWwgZmFjdG9ycywgc3VjaCBhcyB0aGUgaW5jb21lLCB3aGljaCB3b3VsZCBiZSBkaXNjdXNzZWQgaW4gdGhlIGZpbmFsIHBhcnQgb2YgTWFpbiBBbmFseXNpcy4KCmBgYHtyfQojIEVMQQojIFNlcGVyYXRlIEVMQSBzY29yZXMgYnkgeWVhciAyMDA2IH4gMjAxMiBhbmQgMjAxMyB+IDIwMTYKZWxhX3AwNjEyID0gZ2dwbG90KGVsYV9hbGxfc3R1XzA2MTIsIGFlcyh4ID0gWWVhciwgeSA9IERpc3RyaWN0LCBmaWxsID0gTWVhbl9TY2FsZV9TY29yZSkpICsgCiAgICBnZW9tX3RpbGUoKSArCiAgICBzY2FsZV9maWxsX3ZpcmlkaXMoKSArCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDYsIDIwMTYsIDEpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEsIDMyLCAxKSkgKwogICAgY29vcmRfZmxpcCgpICsKICAgIGxhYnModGl0bGUgPSAiQWxsIHN0dWRlbnQgRUxBIE1lYW4gU2NvcmUgYnkgRGlzdHJpY3QgMjAwNiB+IDIwMTIiLCB4ID0gIlllYXIiLCB5ID0gIkRpc3RyaWN0IikKCmVsYV9wMTMxNiA9IGdncGxvdChlbGFfYWxsX3N0dV8xMzE2LCBhZXMoeCA9IFllYXIsIHkgPSBEaXN0cmljdCwgZmlsbCA9IE1lYW5fU2NhbGVfU2NvcmUpKSArIAogICAgZ2VvbV90aWxlKCkgKwogICAgc2NhbGVfZmlsbF92aXJpZGlzKCkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA2LCAyMDE2LCAxKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxLCAzMiwgMSkpICsKICAgIGNvb3JkX2ZsaXAoKSArCiAgICBsYWJzKHRpdGxlID0gIkFsbCBzdHVkZW50IEVMQSBNZWFuIFNjb3JlIGJ5IERpc3RyaWN0IDIwMTMgfiAyMDE2IiwgeCA9ICJZZWFyIiwgeSA9ICJEaXN0cmljdCIpCgpncmlkLmFycmFuZ2UoZWxhX3AwNjEyLCBlbGFfcDEzMTYsIG5yb3cgPSAyKQpgYGAKQnkgdGhpcyBwbG90LCB3ZSBmb3VuZCB0aGF0IGhlYXRtYXAgb2YgTWF0aCBhbmQgRUxBIHBlcmZvcm1hbmNlcyB3ZXJlIHNpbWlsYXIuIEluIGdlbmVyYWwsIHN0dWRlbnQgbWVhbiBzY29yZSBpbmNyZWFzZWQgYXMgdGltZSB3ZW50IGJ5LCB5ZXQgRUxBIGhhZCBleHBlY3RhdGlvbnMgb24geWVhciAyMDExIGFuZCAyMDE0LiBJbiBhZGRpdGlvbiwgY29tcGFyZWQgd2l0aCB5ZWFyIGdyb3VwIDIwMDYgfiAyMDEyLCB0aGUgcmFuZ2Ugb2Ygc3R1ZGVudHMnIG1lYW4gc2NvcmVzIG9uIEVMQSBlbmxhcmdlZCBhcyBtZWFuIHNjb3JlcyBvbiBNYXRoLiBBbmQgdGhlIGRpc3RyaWN0cyB3aXRoIGhpZ2hlciBhdmVyYWdlIE1hdGggc2NvcmVzIGNvcnJlc3BvbmRlZCB0byB0aGUgZGlzdHJpY3RzIHdpdGggaGlnaGVyIGF2ZXJhZ2UgRUxBIHNjb3Jlcy4gVGh1cywgd2UgcmVmZXJyZWQgdGhhdCB0aGVyZSBtaWdodCBiZSBzb21lIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIE1hdGggZXhhbSBwZXJmb3JtYW5jZXMgYW5kIEVMQSBleGFtIHBlcmZvcm1hbmNlcy4gU28sIHdlIGRpZCB0d28gY292YXJpYW5jZSBtYXRyaWNlcyB0byBpbmRpY2F0ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTWF0aCBhbmQgRUxBLgoKCiMjIyAoMykgQ292YXJpYW5jZSBNYXRyaWNlcyBvbiBNYXRoIGFuZCBFTEEgZXhhbSBwZXJmb3JtYW5jZXMKYGBge3J9CmxpYnJhcnkocGx5cikKbWF0aF9hbGwwNjEyIDwtIG1hdGhfYWxsX3N0dV8wNjEyICU+JSAKICBtdXRhdGUoeWVhcl9jYXQgPSAiMDYtMTIiKQptYXRoX2FsbDEzMTYgPC0gbWF0aF9hbGxfc3R1XzEzMTYgJT4lIAogIG11dGF0ZSh5ZWFyX2NhdCA9ICIxMy0xNiIpCmVsYV9hbGwwNjEyIDwtIGVsYV9hbGxfc3R1XzA2MTIgJT4lIAogIG11dGF0ZSh5ZWFyX2NhdCA9ICIwNi0xMiIpCmVsYV9hbGwxMzE2IDwtIGVsYV9hbGxfc3R1XzEzMTYgJT4lIAogIG11dGF0ZSh5ZWFyX2NhdCA9ICIxMy0xNiIpCgptYXRoX2FsbCA9IHJiaW5kKG1hdGhfYWxsMDYxMiwgbWF0aF9hbGwxMzE2KQplbGFfYWxsID0gcmJpbmQoZWxhX2FsbDA2MTIsIGVsYV9hbGwxMzE2KQoKbWF0aF9hbGxzdHVfcm4gPC0gcmVuYW1lKG1hdGhfYWxsLCBjKCJEaXN0cmljdCIgPSAibWF0aF9kaXN0cmljdCIsICJHcmFkZSIgPSAibWF0aF9ncmFkZSIsICJZZWFyIiA9ICJtYXRoX3llYXIiLCAiQ2F0ZWdvcnkiID0gIm1hdGhfY2F0ZWdvcnkiLCAiTnVtYmVyX1Rlc3RlZCIgPSAibWF0aF9udW1fdGVzdCIsICJNZWFuX1NjYWxlX1Njb3JlIiA9ICJtYXRoX21lYW4iLCAibGV2ZWwxIiA9ICJtYXRoX2xldmVsMSIsICJsZXZlbDFfcGVyIiA9ICJtYXRoX2xldmVsMV9wZXIiLCAibGV2ZWwyIiA9ICJtYXRoX2xldmVsMiIsICJsZXZlbDJfcGVyIiA9ICJtYXRoX2xldmVsMl9wZXIiLCAibGV2ZWwzIiA9ICJtYXRoX2xldmVsMyIsICJsZXZlbDNfcGVyIiA9ICJtYXRoX2xldmVsM19wZXIiLCAibGV2ZWw0IiA9ICJtYXRoX2xldmVsNCIsICJsZXZlbDRfcGVyIiA9ICJtYXRoX2xldmVsNF9wZXIiLCAibGV2ZWwzLjQiID0gIm1hdGhfbGV2ZWwzLjQiLCAibGV2ZWwzLjRfcGVyIiA9ICJtYXRoX2xldmVsMy40X3BlciIsICJ5ZWFyX2NhdCIgPSAibWF0aF95ZWFyX2NhdCIpKQplbGFfYWxsc3R1X3JuIDwtIHJlbmFtZShlbGFfYWxsLCBjKCJEaXN0cmljdCIgPSAiZWxhX2Rpc3RyaWN0IiwgIkdyYWRlIiA9ICJlbGFfZ3JhZGUiLCAiWWVhciIgPSAiZWxhX3llYXIiLCAiQ2F0ZWdvcnkiID0gImVsYV9jYXRlZ29yeSIsICJOdW1iZXJfVGVzdGVkIiA9ICJlbGFfbnVtX3Rlc3QiLCAiTWVhbl9TY2FsZV9TY29yZSIgPSAiZWxhX21lYW4iLCAibGV2ZWwxIiA9ICJlbGFfbGV2ZWwxIiwgImxldmVsMV9wZXIiID0gImVsYV9sZXZlbDFfcGVyIiwgImxldmVsMiIgPSAiZWxhX2xldmVsMiIsICJsZXZlbDJfcGVyIiA9ICJlbGFfbGV2ZWwyX3BlciIsICJsZXZlbDMiID0gImVsYV9sZXZlbDMiLCAibGV2ZWwzX3BlciIgPSAiZWxhX2xldmVsM19wZXIiLCAibGV2ZWw0IiA9ICJlbGFfbGV2ZWw0IiwgImxldmVsNF9wZXIiID0gImVsYV9sZXZlbDRfcGVyIiwgImxldmVsMy40IiA9ICJlbGFfbGV2ZWwzLjQiLCAibGV2ZWwzLjRfcGVyIiA9ICJlbGFfbGV2ZWwzLjRfcGVyIiwgInllYXJfY2F0IiA9ICJlbGFfeWVhcl9jYXQiKSkKbWF0aF9lbGEgPC0gY2JpbmQobWF0aF9hbGxzdHVfcm4sIGVsYV9hbGxzdHVfcm4pIAptYXRoX2VsYSA8LSBjYmluZCgiaWQiID0gcm93bmFtZXMobWF0aF9lbGEpLCBtYXRoX2VsYSkKCmRmMSA8LSBzZWxlY3QobWF0aF9lbGEsaWQsc3RhcnRzX3dpdGgoIm0iKSkKZGYyIDwtIHNlbGVjdChtYXRoX2VsYSxpZCxzdGFydHNfd2l0aCgiZSIpKQoKIyBtYXRoIGFuZCBlbGEgY29tcGFyaXNvbgptbWVhbiA8LSBkZjEgJT4lIAogIHNlbGVjdChpZCwgbWF0aF9kaXN0cmljdCwgbWF0aF9tZWFuLCBtYXRoX3llYXJfY2F0KSAlPiUgCiAgZ2F0aGVyKG1hdGhfdmFyLG1hdGhfbWVhbiwtaWQsIC1tYXRoX2Rpc3RyaWN0LCAtbWF0aF95ZWFyX2NhdCkgJT4lIAogIHJlbmFtZSguLCBjKCJtYXRoX2Rpc3RyaWN0IiA9ICJEaXN0cmljdCIsICJtYXRoX21lYW4iID0gInZhbHVlIiwgIm1hdGhfeWVhcl9jYXQiID0gInllYXJfY2F0IikpIAptbGV2ZWwxX3BlciA8LSBkZjEgJT4lIAogIHNlbGVjdChpZCxtYXRoX2Rpc3RyaWN0LCBtYXRoX2xldmVsMV9wZXIsIG1hdGhfeWVhcl9jYXQpICU+JSAKICBnYXRoZXIobWF0aF92YXIsbWF0aF9sZXZlbDFfcGVyLC1pZCwgLW1hdGhfZGlzdHJpY3QsIC1tYXRoX3llYXJfY2F0KSAlPiUgCiAgcmVuYW1lKC4sIGMoIm1hdGhfZGlzdHJpY3QiID0gIkRpc3RyaWN0IiwgIm1hdGhfbGV2ZWwxX3BlciIgPSAidmFsdWUiLCAibWF0aF95ZWFyX2NhdCIgPSAieWVhcl9jYXQiKSkKbWxldmVsMl9wZXIgPC0gZGYxICU+JSAKICBzZWxlY3QoaWQsIG1hdGhfZGlzdHJpY3QsIG1hdGhfbGV2ZWwyX3BlciwgbWF0aF95ZWFyX2NhdCkgJT4lIAogIGdhdGhlcihtYXRoX3ZhcixtYXRoX2xldmVsMl9wZXIsLWlkLCAtbWF0aF9kaXN0cmljdCwgLW1hdGhfeWVhcl9jYXQpICU+JSAKICByZW5hbWUoLiwgYygibWF0aF9kaXN0cmljdCIgPSAiRGlzdHJpY3QiLCAibWF0aF9sZXZlbDJfcGVyIiA9ICJ2YWx1ZSIsICJtYXRoX3llYXJfY2F0IiA9ICJ5ZWFyX2NhdCIpKQptbGV2ZWwzX3BlciA8LSBkZjEgJT4lIAogIHNlbGVjdChpZCwgbWF0aF9kaXN0cmljdCwgbWF0aF9sZXZlbDNfcGVyLCBtYXRoX3llYXJfY2F0KSAlPiUgCiAgZ2F0aGVyKG1hdGhfdmFyLG1hdGhfbGV2ZWwzX3BlciwtaWQsIC1tYXRoX2Rpc3RyaWN0LCAtbWF0aF95ZWFyX2NhdCkgJT4lIAogIHJlbmFtZSguLCBjKCJtYXRoX2Rpc3RyaWN0IiA9ICJEaXN0cmljdCIsICJtYXRoX2xldmVsM19wZXIiID0gInZhbHVlIiwgIm1hdGhfeWVhcl9jYXQiID0gInllYXJfY2F0IikpCm1sZXZlbDRfcGVyIDwtIGRmMSAlPiUgCiAgc2VsZWN0KGlkLCBtYXRoX2Rpc3RyaWN0LCBtYXRoX2xldmVsNF9wZXIsIG1hdGhfeWVhcl9jYXQpICU+JSAKICBnYXRoZXIobWF0aF92YXIsbWF0aF9sZXZlbDRfcGVyLC1pZCwgLW1hdGhfZGlzdHJpY3QsIC1tYXRoX3llYXJfY2F0KSAlPiUgCiAgcmVuYW1lKC4sIGMoIm1hdGhfZGlzdHJpY3QiID0gIkRpc3RyaWN0IiwgIm1hdGhfbGV2ZWw0X3BlciIgPSAidmFsdWUiLCAibWF0aF95ZWFyX2NhdCIgPSAieWVhcl9jYXQiKSkKZGZ0bSA8LSByYmluZChtbGV2ZWwxX3BlciwgbWxldmVsMl9wZXIpICU+JSAKICByYmluZCguLCBtbGV2ZWwzX3BlcikgJT4lIAogIHJiaW5kKC4sIG1sZXZlbDRfcGVyKQoKZW1lYW4gPC0gZGYyICU+JSAKICBzZWxlY3QoaWQsIGVsYV9kaXN0cmljdCwgZWxhX21lYW4sIGVsYV95ZWFyX2NhdCkgJT4lIAogIGdhdGhlcihlbGFfdmFyLGVsYV9tZWFuLC1pZCwgLWVsYV9kaXN0cmljdCwgLWVsYV95ZWFyX2NhdCkgJT4lIAogIHJlbmFtZSguLCBjKCJlbGFfZGlzdHJpY3QiID0gIkRpc3RyaWN0IiwgImVsYV9tZWFuIiA9ICJ2YWx1ZSIsICJlbGFfeWVhcl9jYXQiID0gInllYXJfY2F0IikpCmVsZXZlbDFfcGVyIDwtIGRmMiAlPiUgCiAgc2VsZWN0KGlkLGVsYV9kaXN0cmljdCwgZWxhX2xldmVsMV9wZXIsIGVsYV95ZWFyX2NhdCkgJT4lIAogIGdhdGhlcihlbGFfdmFyLGVsYV9sZXZlbDFfcGVyLC1pZCwgLWVsYV9kaXN0cmljdCwgLWVsYV95ZWFyX2NhdCkgJT4lIAogIHJlbmFtZSguLCBjKCJlbGFfZGlzdHJpY3QiID0gIkRpc3RyaWN0IiwgImVsYV9sZXZlbDFfcGVyIiA9ICJ2YWx1ZSIsICJlbGFfeWVhcl9jYXQiID0gInllYXJfY2F0IikpCmVsZXZlbDJfcGVyIDwtIGRmMiAlPiUgCiAgc2VsZWN0KGlkLGVsYV9kaXN0cmljdCwgZWxhX2xldmVsMl9wZXIsIGVsYV95ZWFyX2NhdCkgJT4lIAogIGdhdGhlcihlbGFfdmFyLGVsYV9sZXZlbDJfcGVyLC1pZCwgLWVsYV9kaXN0cmljdCwgLWVsYV95ZWFyX2NhdCkgJT4lIAogIHJlbmFtZSguLCBjKCJlbGFfZGlzdHJpY3QiID0gIkRpc3RyaWN0IiwgImVsYV9sZXZlbDJfcGVyIiA9ICJ2YWx1ZSIsICJlbGFfeWVhcl9jYXQiID0gInllYXJfY2F0IikpCmVsZXZlbDNfcGVyIDwtIGRmMiAlPiUgCiAgc2VsZWN0KGlkLGVsYV9kaXN0cmljdCwgZWxhX2xldmVsM19wZXIsIGVsYV95ZWFyX2NhdCkgJT4lIAogIGdhdGhlcihlbGFfdmFyLGVsYV9sZXZlbDNfcGVyLC1pZCwgLWVsYV9kaXN0cmljdCwgLWVsYV95ZWFyX2NhdCkgJT4lIAogIHJlbmFtZSguLCBjKCJlbGFfZGlzdHJpY3QiID0gIkRpc3RyaWN0IiwgImVsYV9sZXZlbDNfcGVyIiA9ICJ2YWx1ZSIsICJlbGFfeWVhcl9jYXQiID0gInllYXJfY2F0IikpCmVsZXZlbDRfcGVyIDwtIGRmMiAlPiUgCiAgc2VsZWN0KGlkLGVsYV9kaXN0cmljdCwgZWxhX2xldmVsNF9wZXIsIGVsYV95ZWFyX2NhdCkgJT4lIAogIGdhdGhlcihlbGFfdmFyLGVsYV9sZXZlbDRfcGVyLC1pZCwgLWVsYV9kaXN0cmljdCwgLWVsYV95ZWFyX2NhdCkgJT4lIAogIHJlbmFtZSguLCBjKCJlbGFfZGlzdHJpY3QiID0gIkRpc3RyaWN0IiwgImVsYV9sZXZlbDRfcGVyIiA9ICJ2YWx1ZSIsICJlbGFfeWVhcl9jYXQiID0gInllYXJfY2F0IikpCmRmdGUgPC1yYmluZChlbGV2ZWwxX3BlciwgZWxldmVsMl9wZXIpICU+JSAKICByYmluZCguLCBlbGV2ZWwzX3BlcikgJT4lIAogIHJiaW5kKC4sIGVsZXZlbDRfcGVyKQoKZGZ0IDwtIGRmdG0gJT4lIAogIGxlZnRfam9pbihkZnRlLCBieT0iaWQiKQoKZGZfbWVhbiA8LSBtbWVhbiAlPiUgCiAgbGVmdF9qb2luKGVtZWFuLCBieSA9ICJpZCIpCgpnZ3Bsb3QoZGF0YSA9IGRmdCxhZXMoeCA9IHZhbHVlLngsIHkgPSB2YWx1ZS55KSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbCA9IHllYXJfY2F0LngpLCBhbHBoYSA9IDAuMDUpICsKICBnZW9tX3Ntb290aChhZXMobGluZXR5cGUgPSB5ZWFyX2NhdC54KSwgZmlsbCA9IE5BLCBzaXplID0gMC41KSArCiAgZmFjZXRfZ3JpZChtYXRoX3ZhciB+IGVsYV92YXIpICsKICBsYWJzKHRpdGxlID0gIkNvdmFyaWFuY2UgTWF0cml4IG9uIE1hdGggYW5kIEVMQSBzY29yZXMgb24gZ3JhZGVzIDMgfiA4IDIwMDYgfiAyMDEyIGJ5IGxldmVscyAoMSkiLCB4ID0gIkVMQSBQZXJmb3JtYW5lIExldmVscyBQcm9wb3J0aW9uIiwgeSA9ICJNYXRoIFBlcmZvcm1hbmNlIExldmVscyBQcm9wb3J0aW9uIiwgbGluZXR5cGUgPSAiWWVhciBHcm91cCBMaW5lIiwgY29sID0gIlllYXIgR3JvdXAgUG9pbnQiKQpgYGAKQmVjYXVzZSBvZiB0aGUgc2ltaWxhciBsb29rcyBvbiBoZWF0bWFwcyBvZiBNYXRoIGFuZCBFTEEsIHdlIHdhbnRlZCB0byB2YWxpZGF0ZSBhIGh5cG90aGVzaXMgdGhhdCBzdHVkZW50IHdpdGggaGlnaGVyIHNjb3JlcyBvbiBNYXRoIG9yIEVMQSBwZXJmb3JtcyBiZXR0ZXIgaW4gYW5vdGhlciBzdWJqZWN0IGFzIHdlbGwgaW4gZ2VuZXJhbC4gVGh1cywgd2UgY2hvc2UgQ292YXJpYW5jZSBNYXRyaXggdG8gaW5kaWNhdGUgdGhlIHBvc3NpYmxlIHJlbGF0aW9uc2hpcC4KCkhvd2V2ZXIsIGJlY2F1c2UgdGhlIGZ1bmN0aW9uICJwYWlycyIgYW5kICJwbG90IiBjb3VsZCBub3QgY2xlYXJseSBpbmRpY2F0ZSB0aGUgdHJlbmRzIGJ5IGRpZmZlcmVudCBjYXRlZ29yaWVzLCB3ZSBkaWQgYSBtdWNoIGNvbXBsZXggcHJvY2VkdXJlIHRvIGRyYXcgdGhlIGNvdmFpcmFuY2UgbWF0cml4IHBsb3QuIFRoZSBjaGFsbGVnZSB3ZSBtZXQgd2FzIGNvbWJpbmluZyB0aGUgdXNlZnVsIGluZm9ybWF0aW9uIGludG8gb25lIGRhdGFmcmFtZSBhbmQgdGhlbiB3ZSBjb3VsZCB1c2UgZ2dwbG90MiB0byBwbG90IHdoYXQgd2Ugd2FudGVkLiBXZSB1c2UgcGFja2FnZSAiZHBseXIiIHRvIHNlbGVjdCBhbmQgZ2F0aGVyIHRoZSBkYXRhLiBGaW5hbGx5IHdlIGNvdWxkIGZpZ3VyZSBvdXQgdGhlIHRyZW5kIHdpdGggRUxBIHBlcmZvcm1hbmNlcyBhbmQgTWF0aCBwZXJmb3JtYW5jZXMgYnkgeWVhciBncm91cCwgd2hpY2ggYXZvaWRlZCBlcnJvcnMgY2F1c2VkIGJ5IGRpZmZlcmVudCBleGFtIHN0YW5kYXJkcy4gQW5kIHRoZSByZWFzb24gd2h5IHdlIHVzZWQgZmVhdHVyZSAibGV2ZWxzIiBpbnN0ZWFkIG9mIGZlYXR1cmUgInNjb3JlcyIgaGVyZSB3YXMgYWxzbyB0aGUgc2FtZS4KCkFjY29yZGluZyB0byB0aGUgZ3JhcGggYWJvdmUsIGVzcGVjaWFsbHkgdGhlIHBsb3RzIGluIGRpYWdvbmFsLCB3ZSBjb3VsZCBpbmRpY2F0ZSB0aGF0IHRoZSBwb3Jwcm90aW9uIG9mIHN0dWRlbnRzIGluIGxldmVsTiBpbiBNYXRoIGV4YW1zIHdlcmUgYWxtb3N0IGxpbmVhcmx5IHJlbGF0ZWQgdG8gdGhlIG9uZSBvZiBzdHVkZW50cyBpbiBsZXZlbE4sIHdoaWNoIG1pZ2h0IHNob3cgdGhhdCBzdHVkZW50cyB3aXRoIGhpZ2hlciBNYXRoIHNjb3JlcyBtaWdodCBoYXZlIGhpZ2hlciBFTEEgc2NvcmUgYXMgd2VsbC4gT2J2aW91c2x5LCBUaGlzIGdyYXBoIHZhbGlkYXRlZCBvdXIgaHlwb3RoZXNpcy4KYGBge3J9CiMgTWVhbiBjb3ZhcmlhbmNlCmdncGxvdChkYXRhID0gZGZfbWVhbixhZXMoeCA9IHZhbHVlLngsIHkgPSB2YWx1ZS55KSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbCA9IHllYXJfY2F0LngpLCBhbHBoYSA9IDAuMikgKwogIGdlb21fc21vb3RoKGFlcyhsaW5ldHlwZSA9IHllYXJfY2F0LngpLCBjb2wgPSAiYmxhY2siLCBzaXplID0gMC41KSArCiAgZmFjZXRfZ3JpZChtYXRoX3ZhciB+IGVsYV92YXIpICsKICBsYWJzKHRpdGxlID0gIkNvdmFyaWFuY2UgTWF0cml4IG9uIE1hdGggYW5kIEVMQSBzY29yZXMgb24gZ3JhZGVzIDMgfiA4IDIwMDYgfiAyMDEyIGJ5IE1lYW4gU2NvcmUiLCB4ID0gIkVMQSBzY29yZSIsIHkgPSAiTWF0aCBzY29yZSIpCgpgYGAKSGVyZSB3ZSB1c2VkIG1lYW4gc2NvcmVzIHRvIGluZGljYXRlIHRoZSBnZW5lcmFsIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIEVsYSBhbmQgTWF0aCBieSB5ZWFyIGNhdGVnb3JpZXMuIFdlIGNvdWxkIGZpbmQgdGhhdCBpbiAyMDA2IH4gMjAxNiwgYWxsIHN0dWRlbnRzJyBNYXRoIGFuZCBFTEEgbWVhbiBzY29yZXMgaGFkIHBvc2l0aXZlIGNvcnJlbGF0aW9uLiAKYGBge3J9CmdncGxvdChkYXRhID0gZGZ0LGFlcyh4ID0gdmFsdWUueCwgeSA9IHZhbHVlLnkpKSArCiAgZ2VvbV9zbW9vdGgoYWVzKGNvbCA9IGFzLmZhY3RvcihEaXN0cmljdC54KSwgbGluZXR5cGUgPSB5ZWFyX2NhdC54KSwgZmlsbCA9IE5BLCBzaXplID0gMC41KSArCiAgZmFjZXRfZ3JpZChtYXRoX3ZhciB+IGVsYV92YXIpICsKICBndWlkZXMoY29sID0gRkFMU0UpICsKICBsYWJzKHRpdGxlID0gIkNvdmFyaWFuY2UgTWF0cml4IG9uIE1hdGggYW5kIEVMQSBzY29yZXMgb24gZ3JhZGVzIDMgfiA4IDIwMDYgfiAyMDEyIGJ5IGxldmVscyAoMikiLCB4ID0gIkVMQSBQZXJmb3JtYW5lIExldmVscyBQcm9wb3J0aW9uIiwgeSA9ICJNYXRoIFBlcmZvcm1hbmNlIExldmVscyBQcm9wb3J0aW9uIiwgbGluZXR5cGUgPSAiWWVhciBHcm91cCIpCmBgYApBbmQgdGhlbiwgd2UgYWxzbyB2YWxpZGF0ZWQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN0dWRlbnRzJyBNYXRoIGFuZCBFTEEgcGVyZm9ybWFuY2VzIGJ5IGRpc3RyaWN0cy4gQWx0aG91Z2ggd2UgY291bGQgbm90IGZpZ3VyZSBvdXQgdGhlIHJlbGF0aW9uc2hpcCBmb3Igb25lIHNwZWNpZmljIGRpc3RyaWN0LCB3ZSBzdGlsbCBjb3VsZCBmaWd1cmUgb3V0IHRoZSByZWxhdGlvbnNoaXAgaW4gZ2VuZXJhbC4gQ2xlYXJseSwgZm9yIHN0dWRlbnRzIGluIGRpZmZlcmVudCBkaXN0cmljdHMsIHRoZSBwb3NpdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIE1hdGggYW5kIEVMQSBzY29yZXMgc3RpbGwgZXhpc3RlZC4KCiMjIyBiKSBNYXRoIGFuZCBFTEEgU2NvcmUgQW5hbHlzaXMgYnkgRXRobmljaXR5CgojIyMjIChpKSBIaXN0b2dyYW0gb24gTWVhbiBzY29yZQpgYGB7cn0KI21hdGhfZXRobmljaXR5IAojaGlzdG9ncmFtCm1hdGhfcGhpc3QxIDwtIG1hdGhfZXRobmljaXR5XzEzMTYgJT4lIAogIGdyb3VwX2J5KENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShtZWFuX3Njb3JlID0gbWVhbihNZWFuX1NjYWxlX1Njb3JlLCBuYS5ybSA9IFRSVUUpKSAlPiUgCiAgbXV0YXRlKFN1YmplY3QgPSAiTWF0aCIpCm1hdGhfcGhpc3QyIDwtIG1hdGhfZXRobmljaXR5XzA2MTIgJT4lIAogIGdyb3VwX2J5KENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShtZWFuX3Njb3JlID0gbWVhbihNZWFuX1NjYWxlX1Njb3JlLCBuYS5ybSA9IFRSVUUpKSAlPiUgCiAgbXV0YXRlKFN1YmplY3QgPSAiTWF0aCIpCgplbGFfcGhpc3QxIDwtIGVsYV9ldGhuaWNpdHlfMTMxNiAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKE1lYW5fU2NhbGVfU2NvcmUsIG5hLnJtID0gVFJVRSkpICU+JSAKICBtdXRhdGUoU3ViamVjdCA9ICJFTEEiKQplbGFfcGhpc3QyIDwtIGVsYV9ldGhuaWNpdHlfMDYxMiAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKE1lYW5fU2NhbGVfU2NvcmUsIG5hLnJtID0gVFJVRSkpICU+JQogIG11dGF0ZShTdWJqZWN0ID0gIkVMQSIpCiAgCnBwaGlzdDA2MTIgPC0gcmJpbmQobWF0aF9waGlzdDIsIGVsYV9waGlzdDIpCnBwaGlzdDEzMTYgPC0gcmJpbmQobWF0aF9waGlzdDEsIGVsYV9waGlzdDEpCgpzdWJqZWN0X2hpc3QwNjEyIDwtIGdncGxvdChwcGhpc3QwNjEyLCBhZXMoeCA9IENhdGVnb3J5LCB5ID0gbWVhbl9zY29yZSkpICsKICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIGFlcyhmaWxsID0gU3ViamVjdCkpICsKICAgIGxhYnModGl0bGUgPSAiMjAwNiB+MjAxMiBNZWFuIFNjb3JlIHdpdGggRXRobmljaXR5IiwgeCA9ICJFdGhuaWNpdHkiLCB5ID0gIk1lYW4gU2NvcmUiLCBmaWxsID0gIlllYXIgR3JvdXAiKQpzdWJqZWN0X2hpc3QxMzE2IDwtIGdncGxvdChwcGhpc3QxMzE2LCBhZXMoeCA9IENhdGVnb3J5LCB5ID0gbWVhbl9zY29yZSkpICsKICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIGFlcyhmaWxsID0gU3ViamVjdCkpKwogICAgbGFicyh0aXRsZSA9ICIyMDEzIH4yMDE2IE1lYW4gU2NvcmUgd2l0aCBFdGhuaWNpdHkiLCB4ID0gIkV0aG5pY2l0eSIsIHkgPSAiTWVhbiBTY29yZSIsIGZpbGwgPSAiWWVhciBHcm91cCIpCgpncmlkLmFycmFuZ2Uoc3ViamVjdF9oaXN0MDYxMiwgc3ViamVjdF9oaXN0MTMxNiwgbnJvdyA9IDEpCmBgYApXZSBjaG9zZSBiYXIgY2hhcnQgd2l0aCAiZG9kZ2UiIGhlcmUgYmVjYXVzZSBpdCBjYW4gc2hvdyBFTEEgYW5kIE1hdGggc2NvcmVzIHRvZ2V0aGVyIGFuZCB0aGVpciBoZWlnaHRzLCB3aGljaCB3YXMgY29udmVuaWVudCBmb3IgcmVhZGVycyB0byBjb21wYXJlLiBXZSB0cmllZCB0byBwdXQgcGVyZm9ybWFuY2VzIHdpdGggZGlmZmVyZW50IEV0aG5pY2l0eSBkdXJpbmcgdGhlIHBlcmlvZCAyMDA2IH4gMjAxNiwgYnV0IHRoYXQgbWV0aG9kIG1hZGUgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gZXRobmljaXRpZXMgdW5jbGVhci4KCkFjY29yZGluZyB0byB0aGUgZ3JhcGhzIGFib3ZlLCB3ZSBjb3VsZCBmaWd1cmUgb3V0IHRoYXQgQXNpYW5zIG91dHBlcmZvcm1lZCBpbiBtYXRoIGFuZCBFTEEgZXhhbXMgdGhhbiBvdGhlciBldGhuaWNpdGllcyBhbmQgV2hpdGVzIHBlcmZvcm1lZCBzbGlnaHRseSBiZXR0ZXIgdGhhbiBvdGhlciB0d28gZXRobmljaXRpZXMuIEFuZCBpbiBnZW5lcmFsLCBIaXNwYW5pY3MgcGVyZm9ybWVkIGEgYml0IGJldHRlciB0aGFuIEJsYWNrcy4gSW4gYWRkaXRpb24sIHN0dWRlbnQncyBtYXRoIHNjb3JlcyB3ZXJlIGhpZ2hlciB0aGFuIEVMQSBzY29yZXMgaW4gZ2VuZXJhbC4KCiMjIyMgKGlpKSBMaW5lIGNoYXJ0IG9uIE1lYW4gc2NvcmUgYnkgZGlzdHJpY3QKYGBge3J9CiMgTWF0aCBwY3AgcGxvdApwY3BfbWF0aF9ldGggPC0gbWF0aF9ldGhuaWNpdHlfMTMxNiAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnksIERpc3RyaWN0KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShtZWFuX3Njb3JlPW1lYW4oTWVhbl9TY2FsZV9TY29yZSwgbmEucm0gPSBUUlVFKSkgJT4lIAogIG11dGF0ZSh5ZWFyX2NhdCA9ICIxMy0xNiIpCnBjcF9tYXRoX2V0aDIgPC0gbWF0aF9ldGhuaWNpdHlfMDYxMiAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnksIERpc3RyaWN0KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShtZWFuX3Njb3JlID0gbWVhbihNZWFuX1NjYWxlX1Njb3JlLCBuYS5ybSA9IFRSVUUpKSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjA2LTEyIikKCnBjcF9tYXRoIDwtIHJiaW5kKHBjcF9tYXRoX2V0aCwgcGNwX21hdGhfZXRoMikKCmdncGxvdChwY3BfbWF0aCwgYWVzKHggPSBEaXN0cmljdCwgIHkgPSBtZWFuX3Njb3JlLCBjb2wgPSBDYXRlZ29yeSkpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlID0geWVhcl9jYXQpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxLCAzMiwgMSkpICsKICBsYWJzKHRpdGxlID0gIlN0dWRlbnQgTWF0aCBNZWFuIFNjb3JlIHdpdGggRXRobmljaXR5IGFuZCBEaXN0cmljdCIsIHggPSAiRGlzdHJpY3QiLCB5ID0gIk1lYW4gU2NvcmUiLCBjb2wgPSAiRXRobmljaXR5IiwgbGluZXR5cGUgPSAiWWVhciBHcm91cCIpCmBgYApCZWNhdXNlIHRoaXMgcGxvdCBpcyBlYXN5IHRvIGZpZ3VyZSBvdXQgYW5kIGNvbXBhcmUgdGhlIHRyZW5kcyBjb21wYXJlZCB0byBhIGJhciBjaGFydCwgd2UgY2hvc2UgbGluZSBjaGFydCB0byBpbmRpY2F0ZSB0aGUgb3ZlcmFsbCB0cmVuZHMgYnkgdGhlIGRpc3RyaWN0IHRocm91Z2ggZGlmZmVyZW50IGV0aG5pY2l0aWVzLgoKQWNjb3JkaW5nIHRvIHRoZSBwbG90IGFib3ZlLCB3ZSBmb3VuZCB0aGF0IEFzaWFucycgbWF0aCBzY29yZXMgd2VyZSBxdWl0ZSBzdGFibGUgYnkgZGlzdHJpY3QgYW5kIFdoaXRlcycgbWF0aCBzY29yZXMgd2VyZSB2YXJpb3VzIHRocm91Z2ggZGlzdHJpY3RzLiBUaGUgcGFyYWxsZWwgY29vcmRpbmF0ZXMgcGxvdCBhYm92ZSBjbGVhcmx5IHNob3dlZCB0aGF0IHRoZSBzaGFwZXMgb2YgbGluZXMgYnkgdHdvIGRpZmZlcmVudCBncm91cHMgd2VyZSBhbG1vc3QgdGhlIHNhbWUsIHdoaWNoIGluZGljYXRlZCB0aGF0IHN0dWRlbnRzJyBhY2FkZW1pYyBwZXJmb3JtYW5jZXMgc3RheWVkIHN0YWJsZSB3aXRoIHRpbWUgdGhyb3VnaCBkaWZmZXJlbnQgZGlzdHJpY3RzLiBNb3Jlb3Zlciwgd2hhdCB3YXMgc3VycHJpc2VkIHdhcyB0aGF0IGF0IERpc3RyaWN0IDksIDE2LCAxNywgMTgsIDE5IGFuZCAyMywgV2hpdGVzIHBlcmZvcm1lZCBldmVuIHdvcnNlIHRoYW4gSGlzcGFuaWNzIGFuZCBCbGFja3MuIFRoZXJlIG1pZ2h0IGJlIHNvbWUgcmVhc29uIGZvciB0aGlzIHBoZW5vbWVub24uCgpgYGB7cn0KI2VsYV9ldGhuaWNpdHkgMjAxMyB+MjAxNgojcGNwIHBsb3QKcGNwX2VsYV9ldGggPC0gZWxhX2V0aG5pY2l0eV8xMzE2ICU+JSAKICBncm91cF9ieShDYXRlZ29yeSwgRGlzdHJpY3QpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKE1lYW5fU2NhbGVfU2NvcmUsIG5hLnJtID0gVFJVRSkpICU+JSAKICBtdXRhdGUoeWVhcl9jYXQgPSAiMTMtMTYiKQpwY3BfZWxhX2V0aDIgPC0gZWxhX2V0aG5pY2l0eV8wNjEyICU+JSAKICBncm91cF9ieShDYXRlZ29yeSwgRGlzdHJpY3QpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKE1lYW5fU2NhbGVfU2NvcmUsIG5hLnJtID0gVFJVRSkpICU+JSAKICBtdXRhdGUoeWVhcl9jYXQgPSAiMDYtMTIiKQpwY3BfZWxhIDwtIHJiaW5kKHBjcF9lbGFfZXRoLCBwY3BfZWxhX2V0aDIpCgpnZ3Bsb3QocGNwX2VsYSwgYWVzKHggPSBEaXN0cmljdCwgIHkgPSBtZWFuX3Njb3JlLCBjb2wgPSBDYXRlZ29yeSkpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlID0geWVhcl9jYXQpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxLCAzMiwgMSkpICsKICBsYWJzKHRpdGxlID0gIlN0dWRlbnQgRUxBIE1lYW4gU2NvcmUgd2l0aCBFdGhuaWNpdHkgYW5kIERpc3RyaWN0IiwgeCA9ICJEaXN0cmljdCIsIHkgPSAiUmVsZXRpdmUgdmFsdWUiLCBjb2wgPSAiRXRobmljaXR5IiwgbGluZXR5cGUgPSAiWWVhciBHcm91cCIpCgpgYGAKVGhlIHBhcmFsbGVsIGNvb3JkaW5hdGVzIHBsb3QgYWJvdmUgY2xlYXJseSBzaG93ZWQgdGhhdCB0aGUgc2hhcGVzIG9mIGxpbmVzIGJ5IHR3byBkaWZmZXJlbnQgZ3JvdXBzIHdlcmUgYWxtb3N0IHRoZSBzYW1lLCB3aGljaCBpbmRpY2F0ZWQgdGhhdCBzdHVkZW50cycgYWNhZGVtaWMgcGVyZm9ybWFuY2VzIHN0YXllZCBzdGFibGUgd2l0aCB0aW1lIHRocm91Z2ggZGlmZmVyZW50IGRpc3RyaWN0cy4gTW9yZW92ZXIsIHdoYXQgc2hvY2tlZCB1cyB3YXMgdGhhdCBhdCBEaXN0cmljdCA3LCA5LCAxNiwgMTcsIDE4LCAxOSBhbmQgMjMgaW4gdGhlIHllYXIgMjAxMyB0byAyMDE2LCBXaGl0ZXMgcGVyZm9ybWVkIGV2ZW4gd29yc2UgdGhhbiBIaXNwYW5pY3MgYW5kIEJsYWNrcywgd2hpY2ggYXBwZWFyZWQgdGhlIHNhbWUgcGhlbm9tZW5vbiBpbiBNYXRoLiAKCgojIyMgYykgTWF0aCBTY29yZSBBbmFseXNpcyBieSBHZW5kZXIKCiMjIyMgKGkpIExpbmUgY2hhcnQgbWF0aCBzY29yZSBhbmFseXNpcyBieSBnZW5kZXIsIGdyYWRlIGFuZCB5ZWFyIGdyb3VwCmBgYHtyfQojbWF0aF9nZW5kZXIgCiNwY3AgbWF0aCBzY29yZSBieSBnZW5kZXIsIGdyYWRlIGFuZCB5ZWFyIGdyb3VwCnBjcF9nZW5kZXIwNjEyIDwtIG1hdGhfZ2VuZGVyXzA2MTIgJT4lCiAgZ3JvdXBfYnkoR3JhZGUsIENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShsZXZlbDFfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDEpL3N1bShOdW1iZXJfVGVzdGVkKSwgbGV2ZWwyX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwyKS9zdW0oTnVtYmVyX1Rlc3RlZCksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMykvc3VtKE51bWJlcl9UZXN0ZWQpLCBsZXZlbDRfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDQpL3N1bShOdW1iZXJfVGVzdGVkKSkgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjA2LTEyIikKCnBjcF9nZW5kZXIxMzE2IDwtIG1hdGhfZ2VuZGVyXzEzMTYgJT4lCiAgZ3JvdXBfYnkoR3JhZGUsIENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShsZXZlbDFfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDEpL3N1bShOdW1iZXJfVGVzdGVkKSwgbGV2ZWwyX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwyKS9zdW0oTnVtYmVyX1Rlc3RlZCksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMykvc3VtKE51bWJlcl9UZXN0ZWQpLCBsZXZlbDRfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDQpL3N1bShOdW1iZXJfVGVzdGVkKSkgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjEzLTE2IikKCnBjcF9nZW5kZXIgPSByYmluZChwY3BfZ2VuZGVyMDYxMiwgcGNwX2dlbmRlcjEzMTYpCgpnZ3Bsb3QocGNwX2dlbmRlciwgYWVzKHggPSBhcy5udW1lcmljKGFzLmZhY3RvcihMZXZlbHMpKSwgeSA9IFByb3BvcnRpb24sIGNvbCA9IEdyYWRlLCBhbHBoYSA9IHllYXJfY2F0KSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBDYXRlZ29yeSkpICsKICBzY2FsZV9hbHBoYV9kaXNjcmV0ZShyYW5nZSA9IGMoMC40LCAxKSkgKwogIGxhYnModGl0bGUgPSAiU3R1ZGVudCBNYXRoIFNjb3JlIExldmVscyBQcm9wb3J0aW9uIHcuci50IEdlbmRlciwgR3JhZGUgYW5kIFllYXIgZ3JvdXAiLCB4ID0gIk1hdGggU2NvcmUgTGV2ZWxzIiwgeSA9ICJQcm9wb3J0aW9uIiwgbGluZXR5cGUgPSAiR2VuZGVyIiwgYWxwaGEgPSJZZWFyIEdyb3VwIiwgY29sID0gIkdyYWRlIikgCmBgYApIZXJlIHdlIGFsc28gY2hvc2UgbGluZSBjaGFydCB0byBpbmRpY2F0ZSB0aGUgb3ZlcmFsbCB0cmVuZHMgb2YgcGVyZm9ybWFuY2VzIG9uIGxldmVscyBieSBkaWZmZXJlbnQgZ3JhZGUsIGdlbmRlciwgYW5kIHllYXIgZ3JvdXAuIFRoaXMgcGxvdCBjb3VsZCBjbGVhcmx5IGNvbXBhcmUgdGhlc2UgdGhyZWUgY2F0ZWdvcmllcyB3aXRoaW4gb25lIHBsb3QsIHdoaWNoIHdhcyBtb3JlIGluZm9ybWF0aXZlIHRoYW4gc2luZ2xlIGJhciBjaGFydCBmb3IgcmVhZGVycy4KCkFjY29yZGluZyB0byB0aGUgcGxvdCBhYm92ZSwgd2UgY291bGQgZmlndXJlIG91dCBzb21lIGluZm9ybWF0aW9uIGJ5IHRocmVlIGRpbWVuc2lvbnMgd2l0aCBsZXZlbHMgZGVmaW5pdGlvbi4KCjEuIExldmVscyBEZWZpbml0aW9uOiAKTllTIExldmVsIDE6IFN0dWRlbnRzIHBlcmZvcm1pbmcgYXQgdGhpcyBsZXZlbCBhcmUgd2VsbCBiZWxvdyBwcm9maWNpZW50IGluIHN0YW5kYXJkcyBmb3IgdGhlaXIgZ3JhZGUuCk5ZUyBMZXZlbCAyOiBTdHVkZW50cyBwZXJmb3JtaW5nIGF0IHRoaXMgbGV2ZWwgYXJlIHBhcnRpYWxseSBwcm9maWNpZW50IGluIHN0YW5kYXJkcyBmb3IgdGhlaXIgZ3JhZGUuIApOWVMgTGV2ZWwgMzogU3R1ZGVudHMgcGVyZm9ybWluZyBhdCB0aGlzIGxldmVsIGFyZSBwcm9maWNpZW50IGluIHN0YW5kYXJkcyBmb3IgdGhlaXIgZ3JhZGUuIApOWVMgTGV2ZWwgNDogU3R1ZGVudHMgcGVyZm9ybWluZyBhdCB0aGlzIGxldmVsIGV4Y2VsIGluIHN0YW5kYXJkcyBmb3IgdGhlaXIgZ3JhZGUuIAoKMi4gR2VuZGVyKGxpbmUgYW5kIGRvdCBsaW5lKToKV2UgY291bGQgaW5kaWNhdGUgdGhhdCBmZW1hbGVzIHBlcmZvcm1lZCBzbGlnaHRseSBiZXR0ZXIgdGhhbiBtYWxlcyBpbiBtYXRoIGV4YW1zLCBpbiB0aGF0IHRoZSBwcm9wb3J0aW9ucyBvZiBmZW1hbGVzIGluIGxldmVsMyBhbmQgbGV2ZWw0IHdlcmUgYSBsaXR0bGUgYml0IGxhcmdlciB0aGFuIG9mIG1hbGVzLCB3aGlsZSB0aGUgcHJvcG9ydGlvbnMgb2YgbWFsZXMgaW4gbGV2ZWwxIGFuZCBsZXZlbDIgd2VyZSBhIGJpdCBsYXJnZXIgdGhhbiBvZiBmZW1hbGVzLgoKMy4gWWVhciBncm91cCAodHJhbnNwYXJlbmN5IGluIDAuNCBhbmQgMSk6CldlIGNvdWxkIGNsZWFybHkgb2JzZXJ2ZSB0aGF0IGluIHllYXIgZ3JvdXAgMDYtMTIsIHRoZXJlIHdhcyB0aGUgbGFyZ2VzdCBwcm9wb3J0aW9uIG9uIGxldmVsMyBhbmQgYmVjYW1lIGxlc3MgYW5kIGxlc3Mgb24gbGV2ZWwyIHRoZW4gbGV2ZWwxLiBBbmQgYXJvdW5kIDI1JSBzdHVkZW50cyB3ZXJlIGluIGxldmVsNCB3aXRoIGV4Y2VsbGVudCBwZXJmb3JtYW5jZS4gSG93ZXZlciwgYmVjYXVzZSBvZiB0aGUgcmFpc2luZyBzdGFuZGFyZCBpbiBleGFtcywgaW4gdGhlIHllYXIgZ3JvdXAgMTMtMTYsIHRoZSBwcm9wb3J0aW9uIG9mIHN0dWRlbnRzJyBtYXRoIHBlcmZvcm1hbmNlcyB3YXMgaW52ZXJzZWx5IHByb3BvcnRpb25hbCB0byBsZXZlbHMuIFRoaXMgcGxvdCBjb2luY2lkZWQgd2l0aCBvdXIgZm9ybWVyIGFuYWx5c2lzIGluIGFsbCBzdHVkZW50IG1hdGggc2NvcmUgaW4gMjAwNn4yMDEyIGFuZCAyMDEzfjIwMTYgdGhhdCB0aGUgZGlmZmVyZW5jZXMgb24gc3R1ZGVudHMnIG1hdGggZXhhbSBwZXJmb3JtYW5jZXMgd2VyZSBncmVhdGVyIGFzIHRoZSBkZWdyZWUgb2YgZGlmZmljdWx0eSBvZiBtYXRoIGV4YW0gaW5jcmVhc2VkLiAKCjQuIEdyYWRlKGNvbG9yIG9mIGxpbmVzKToKSW4gdGhlIGNvbmRpdGlvbiBvZiB0aGUgaGlnaGVyIHN0YW5kYXJkIG9uIG1hdGggZXhhbXMoeWVhcnMgMjAxMyB0byAyMDE2KSwgdGhlIGhpZ2hlciBncmFkZSBzdHVkZW50cyB3ZXJlIGluLCB0aGUgZ3JlYXRlciBzY29yZSBkaWZmZXJlbmNlIHdvdWxkIGJlLiBGb3IgZXhhbXBsZSwgc3R1ZGVudHMgaW4gZ3JhZGU4IGhhZCBsYXJnZXIgcHJvcG9ydGlvbiBvbiBsZXZlbDEgYW5kIGxldmVsNCB0aGFuIGdyYWRlNS4KSW4gdGhlIGNvbmRpdGlvbiBvZiBlYXNpZXIgZGlmZmljdWx0eSBvbiBtYXRoIGV4YW1zICh5ZWFycyAyMDA2IHRvIDIwMTMpLCB0aGUgbG93ZXIgZ3JhZGUgc3R1ZGVudHMgd2VyZSBpbiwgdGhlIGdyZWF0ZXIgc2NvcmUgZGlmZmVyZW5jZSB3b3VsZCBiZS4gRm9yIGluc3RhbmNlLCBzdHVkZW50cyBpbiBncmFkZSAzIG1ha2UgdXAgbW9yZSB0aGFuIGdyYWRlOCBpbiBsZXZlbDMgYW5kIGxlc3MgaW4gbGV2ZWwxIGFuZCBsZXZlbDIuCgpgYGB7cn0KIyBFTEEgYW5hbHlzaXMgb24gZ2VuZGVyIAojcGNwIEVMQSBzY29yZSBieSBnZW5kZXIsIGdyYWRlIGFuZCB5ZWFyIGdyb3VwCmVsYV9wY3BfZ2VuZGVyMDYxMiA8LSBlbGFfZ2VuZGVyXzA2MTIgJT4lCiAgZ3JvdXBfYnkoR3JhZGUsIENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShsZXZlbDFfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDEpL3N1bShOdW1iZXJfVGVzdGVkKSwgbGV2ZWwyX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwyKS9zdW0oTnVtYmVyX1Rlc3RlZCksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMykvc3VtKE51bWJlcl9UZXN0ZWQpLCBsZXZlbDRfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDQpL3N1bShOdW1iZXJfVGVzdGVkKSkgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjA2LTEyIikKCmVsYV9wY3BfZ2VuZGVyMTMxNiA8LSBlbGFfZ2VuZGVyXzEzMTYgJT4lCiAgZ3JvdXBfYnkoR3JhZGUsIENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShsZXZlbDFfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDEpL3N1bShOdW1iZXJfVGVzdGVkKSwgbGV2ZWwyX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwyKS9zdW0oTnVtYmVyX1Rlc3RlZCksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMykvc3VtKE51bWJlcl9UZXN0ZWQpLCBsZXZlbDRfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDQpL3N1bShOdW1iZXJfVGVzdGVkKSkgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjEzLTE2IikKCmVsYV9wY3BfZ2VuZGVyID0gcmJpbmQoZWxhX3BjcF9nZW5kZXIwNjEyLCBlbGFfcGNwX2dlbmRlcjEzMTYpCgpnZ3Bsb3QoZWxhX3BjcF9nZW5kZXIsIGFlcyh4ID0gYXMubnVtZXJpYyhhcy5mYWN0b3IoTGV2ZWxzKSksIHkgPSBQcm9wb3J0aW9uLCBjb2wgPSBHcmFkZSwgYWxwaGEgPSB5ZWFyX2NhdCkpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlID0gQ2F0ZWdvcnkpKSArCiAgc2NhbGVfYWxwaGFfZGlzY3JldGUocmFuZ2UgPSBjKDAuNCwgMSkpICsKICBsYWJzKHRpdGxlID0gIlN0dWRlbnQgRUxBIFNjb3JlIExldmVscyBQcm9wb3J0aW9uIHcuci50IEdlbmRlciwgR3JhZGUgYW5kIFllYXIgZ3JvdXAiLCB4ID0gIkVMQSBTY29yZSBMZXZlbHMiLCB5ID0gIlByb3BvcnRpb24iLCBsaW5ldHlwZSA9ICJHZW5kZXIiLCBhbHBoYSA9IlllYXIgR3JvdXAiLCBjb2wgPSAiR3JhZGUiKSAKYGBgCkFjY29yZGluZyB0byB0aGUgcGxvdCBhYm92ZSwgd2UgY291bGQgZmlndXJlIG91dCBzb21lIGluZm9ybWF0aW9uIGJ5IHRocmVlIGRpbWVuc2lvbnMgd2l0aCBsZXZlbHMgZGVmaW5pdGlvbiBtZW50aW9uZWQgYWJvdmUuCgoxLiBHZW5kZXIobGluZSBhbmQgZG90IGxpbmUpOgpXZSBjb3VsZCBpbmRpY2F0ZSB0aGF0IGZlbWFsZXMgcGVyZm9ybWVkIGJldHRlciB0aGFuIG1hbGVzIGluIEVMQSBleGFtcyB3aXRoIGdyZWF0ZXIgZGlmZmVyZW5jZSB0aGFuIGluIE1hdGggZXhhbXMsIGluIHRoYXQgdGhlIHByb3BvcnRpb25zIG9mIGZlbWFsZXMgaW4gbGV2ZWwzIGFuZCBsZXZlbDQgd2VyZSBhIGxpdHRsZSBiaXQgbGFyZ2VyIHRoYW4gb2YgbWFsZXMsIHdoaWxlIHRoZSBwcm9wb3J0aW9ucyBvZiBtYWxlcyBpbiBsZXZlbDEgYW5kIGxldmVsMiB3ZXJlIGEgYml0IGxhcmdlciB0aGFuIG9mIGZlbWFsZXMuIAoKMi4gWWVhciBncm91cCh0cmFuc3BhcmVuY3kgaW4gMC40IGFuZCAxKToKV2UgY291bGQgY2xlYXJseSBvYnNlcnZlIHRoYXQgaW4geWVhciBncm91cCAwNi0xMiwgdGhlcmUgd2FzIHRoZSBsYXJnZXN0IHByb3BvcnRpb24gb24gbGV2ZWwzIGZvciBmZW1hbGVzIGFuZCB0aGUgbGFyZ2VzdCBwcm9wb3J0aW9uIG9uIGxldmVsMiBmb3IgbWFsZXMuIEFuZCBsZXNzIHRoYW4gMTAlIHN0dWRlbnRzIHdlcmUgaW4gbGV2ZWw0IHdpdGggZXhjZWxsZW50IHBlcmZvcm1hbmNlLiBIb3dldmVyLCBiZWNhdXNlIG9mIHRoZSByYWlzaW5nIHN0YW5kYXJkIGluIGV4YW1zLCBmcm9tIGxldmVsMiB0byBsZXZlbDQgaW4gdGhlIHllYXIgZ3JvdXAgMTMtMTYsIHRoZSBwcm9wb3J0aW9uIG9mIHN0dWRlbnRzJyBtYXRoIHBlcmZvcm1hbmNlcyB3YXMgaW52ZXJzZWx5IHByb3BvcnRpb25hbCB0byBsZXZlbC4gV2hhdCBzdXJwcmlzZWQgdXMgd2FzIHRoYXQgYWx0aG91Z2ggdGhlIHN0YW5kYXJkIHJhaXNlZCBhbmQgbWVhbiBzY29yZXMgZGVjcmVhc2VkIHNoYXJwbHksIHN0dWRlbnRzIGluIGxldmVsNCBpbiB5ZWFyIGdyb3VwIDIwMTMgfiAyMDE2IHdlcmUgbW9yZSB0aGFuIGluIHllYXIgZ3JvdXAgMjAwNiB+IDIwMTIuCgozLiBHcmFkZShjb2xvciBvZiBsaW5lcyk6CkZvciBFTEEgZ3JhZGUsIGl0IHNlZW1zIHRoYXQgc3R1ZGVudHMnIGdyYWRlcyB3ZXJlIG5vdCByZWxhdGVkIHRvIEVMQSBzY29yZXMuCgoKIyMjIyAoaWkpIEdlbmRlciBjb21wYXJpc29uIG9uIHByb3BvcnRpb24gaW4gc3RhY2tzIHBsb3QgCmBgYHtyfQojIE1hdGgKI2dlbmRlciBjb21wYXJpc29uIHdpdGggc3RhY2tzCmdncGxvdChwY3BfZ2VuZGVyLCBhZXMoeCA9IENhdGVnb3J5LCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IGZhY3RvcihMZXZlbHMsIGxldmVscyA9IGMoImxldmVsNF9wcm9wb3J0aW9uIiwgImxldmVsM19wcm9wb3J0aW9uIiwgImxldmVsMl9wcm9wb3J0aW9uIiwgImxldmVsMV9wcm9wb3J0aW9uIikpKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZmFjZXRfZ3JpZCh5ZWFyX2NhdCB+IEdyYWRlKSArCiAgbGFicyh0aXRsZSA9ICJTdHVkZW50IE1hdGggU2NvcmUgTGV2ZWxzIGJ5IGdlbmRlciBjb21wYXJpc29uIiwgeCA9ICJHZW5kZXIiLCB5ID0gIlByb3BvcnRpb24iLCBmaWxsID0gIkxldmVscyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKQpgYGAKQmVjYXVzZSB0aGUgdG90YWwgcHJvcG9ydGlvbnMgb2Ygc3R1ZGVudHMgaW4gZGlmZmVyZW50IGxldmVscyB3ZXJlIDEwMCUgc28gd2UgY2hvc2Ugc3RhY2tlZCBiYXIgY2hhcnRzIHRvIGFuYWx5emUgdGhlIHBlcmZvcm1hbmNlIGRpZmZlcmVuY2VzIGJldHdlZW4gTWFsZXMgYW5kIEZlbWFsZXMuCgpBY2NvcmRpbmcgdG8gdGhlIGdyYXBoIGFib3ZlLCB3ZSBjb3VsZCBmaWd1cmUgb3V0IHRoYXQgdGhlIHBlcmZvcm1hbmNlcyBvZiBmZW1hbGVzIGFuZCBtYWxlcyB3ZXJlIGFsbW9zdCB0aGUgc2FtZSwgYW5kIGZlbWFsZXMnIHBlcmZvcm1hbmNlcyB3ZXJlIHNsaWdodGx5IGJldHRlciB0aGFuIG1hbGVzJy4gVGhpcyB3YXMgYmVjYXVzZSB0aGUgcHJvcG9ydGlvbiBsaW5lIG9mIG1hbGVzJyBwZXJmb3JtYW5jZSB3YXMgYSBsaXR0bGUgYml0IGhpZ2hlciB0aGFuIGZlbWFsZXMnLCBjb3JyZXNwb25kaW5nIHRvIG1vcmUgbG93ZXItbGV2ZWwgcGVyZm9ybWFuY2VzIGJ5IG1hbGVzLgoKYGBge3J9CiMgZWxhCiNnZW5kZXIgY29tcGFyaXNvbiB3aXRoIHN0YWNrcwpnZ3Bsb3QoZWxhX3BjcF9nZW5kZXIsIGFlcyh4ID0gQ2F0ZWdvcnksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gZmFjdG9yKExldmVscywgbGV2ZWxzID0gYygibGV2ZWw0X3Byb3BvcnRpb24iLCAibGV2ZWwzX3Byb3BvcnRpb24iLCAibGV2ZWwyX3Byb3BvcnRpb24iLCAibGV2ZWwxX3Byb3BvcnRpb24iKSkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBmYWNldF9ncmlkKHllYXJfY2F0IH4gR3JhZGUpICsKICBsYWJzKHRpdGxlID0gIlN0dWRlbnQgRUxBIFNjb3JlIExldmVscyBieSBnZW5kZXIgY29tcGFyaXNvbiIsIHggPSAiR2VuZGVyIiwgeSA9ICJQcm9wb3J0aW9uIiwgZmlsbCA9ICJMZXZlbHMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQocmV2ZXJzZT1UUlVFKSkKYGBgCkFjY29yZGluZyB0byB0aGUgZ3JhcGggYWJvdmUsIHdlIGNvdWxkIGZpbmQgdGhhdCBmZW1hbGVzIHBlcmZvcm1lZCBiZXR0ZXIgdGhhbiBtYWxlcyBpbiBhbGwgZ3JhZGVzLCBlc3BlY2lhbGx5IHdoZW4gdGhlIGV4YW0gc3RhbmRhcmRzIHJhaXNlZC4gTW9yZW92ZXIsIHRoaXMgcGxvdCBhbHNvIGNvcnJlc3BvbmRlZCB0byBvdXIgZm9ybWVyIGNvbmNsdXNpb24gdGhhdCBzdHVkZW50cyBpbiBkaWZmZXJlbnQgZ3JhZGVzIGhhZCBzaW1pbGFyIHBlcmZvcm1hbmNlcyBpbiBFTEEgZXhhbXMuIEFuZCB3aXRoIGhpZ2hlciBzdGFuZGFyZHMsIHN0dWRlbnRzIHBlcmZvcm1lZCBiZXR0ZXIgaW4gZXhjZWxsZW50IChsZXZlbDQpLCBtdWNoIGxlc3MgaW4gZ29vZCAobGV2ZWwzKSBhbmQgaW5jcmVhc2luZyBhbW91bnQgaW4gYmFkIChsZXZlbDEpLgoKCgojIyMgZCkgTWF0aCBTY29yZSBBbmFseXNpcyBieSBEaXNhYmlsaXR5IFN0YXR1cwoKIyMjIyBBbmFseXNpcyB3aXRoIGdyYWRlcywgeWVhciBncm91cCwgYW5kIFNXRCBDYXRlZ29yeSBvbiBzdGFjayBwbG90IApgYGB7cn0KI21hdGggU1dEKHN0dWRlbnQgd2l0aCBkaXNhYmlsaXR5KQpwbG90X3N3ZDA2MTIgPC0gbWF0aF9zd2RfMDYxMiAlPiUKICBncm91cF9ieShHcmFkZSwgQ2F0ZWdvcnkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKGxldmVsMV9wcm9wb3J0aW9uID0gc3VtKGxldmVsMSwgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWwyX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwyLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDNfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDMsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsNF9wcm9wb3J0aW9uID0gc3VtKGxldmVsNCwgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSkgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjA2LTEyIikKCnBsb3Rfc3dkMTMxNiA8LSBtYXRoX3N3ZF8xMzE2ICU+JQogIGdyb3VwX2J5KEdyYWRlLCBDYXRlZ29yeSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2UobGV2ZWwxX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwxLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDJfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDIsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMywgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWw0X3Byb3BvcnRpb24gPSBzdW0obGV2ZWw0LCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpKSAgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjEzLTE2IikKCnBsb3Rfc3dkID0gcmJpbmQocGxvdF9zd2QwNjEyLCBwbG90X3N3ZDEzMTYpCgpnZ3Bsb3QocGxvdF9zd2QsIGFlcyh4ID0gQ2F0ZWdvcnksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gZmFjdG9yKExldmVscywgbGV2ZWxzID0gYygibGV2ZWw0X3Byb3BvcnRpb24iLCAibGV2ZWwzX3Byb3BvcnRpb24iLCAibGV2ZWwyX3Byb3BvcnRpb24iLCAibGV2ZWwxX3Byb3BvcnRpb24iKSkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBmYWNldF9ncmlkKHllYXJfY2F0IH4gR3JhZGUpICsKICBsYWJzKHRpdGxlID0gIk1hdGggU2NvcmUgTGV2ZWxzIGJ5IERpc2FiaWxpdHkgb3IgTm90IiwgeCA9ICJEaXNhYmlsaXR5IFN0YXR1cyIsIHkgPSAiUHJvcG9ydGlvbiIsIGZpbGwgPSAiTGV2ZWxzIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHJldmVyc2U9VFJVRSkpCmBgYApXZSBhbHNvIHVzZWQgc3RhY2tlZCBiYXIgY2hhcnRzIGZvciBTV0QgYW5hbHlzZXMgYXMgd2VsbC4gVGhlIGNvbXBhcmlzb24gd2FzIHZlcnkgYXBwYXJlbnQgYnkgc3RhY2sgYmFyIGNoYXJ0cy4KCk9idmlvdXNseSwgc3R1ZGVudHMgd2l0aCBhIGRpc2FiaWxpdHkgKFNXRCkgcGVyZm9ybWVkIG11Y2ggd29yc2UgdGhhbiBzdHVkZW50cyB3aXRob3V0IGEgZGlzYWJpbGl0eS4gTW9yZW92ZXIsIGluIGdlbmVyYWwsIHRoZSBoaWdoZXIgZ3JhZGUgdGhlIHN0dWRlbnRzIHdlcmUgaW4sIHRoZSB3b3JzZSB0aGUgcGVyZm9ybWFuY2VzIG9mIHN0dWRlbnRzIGJvdGggaW4gU1dEIGFuZCBub3RTV0QgZ3JvdXBzLgoKYGBge3J9CiNtYXRoIEVMQShzdHVkZW50IHdpdGggZGlzYWJpbGl0eSkKZWxhX3Bsb3Rfc3dkMDYxMiA8LSBlbGFfc3dkXzA2MTIgJT4lCiAgZ3JvdXBfYnkoR3JhZGUsIENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShsZXZlbDFfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDEsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsMl9wcm9wb3J0aW9uID0gc3VtKGxldmVsMiwgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWwzX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwzLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDRfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDQsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSkpICU+JSAKICBnYXRoZXIoTGV2ZWxzLCBQcm9wb3J0aW9uLCAtR3JhZGUsIC1DYXRlZ29yeSkgJT4lIAogIG11dGF0ZSh5ZWFyX2NhdCA9ICIwNi0xMiIpCgplbGFfcGxvdF9zd2QxMzE2IDwtIGVsYV9zd2RfMTMxNiAlPiUKICBncm91cF9ieShHcmFkZSwgQ2F0ZWdvcnkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKGxldmVsMV9wcm9wb3J0aW9uID0gc3VtKGxldmVsMSwgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWwyX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwyLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDNfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDMsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsNF9wcm9wb3J0aW9uID0gc3VtKGxldmVsNCwgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSkgICU+JSAKICBnYXRoZXIoTGV2ZWxzLCBQcm9wb3J0aW9uLCAtR3JhZGUsIC1DYXRlZ29yeSkgJT4lIAogIG11dGF0ZSh5ZWFyX2NhdCA9ICIxMy0xNiIpCgplbGFfcGxvdF9zd2QgPSByYmluZChlbGFfcGxvdF9zd2QwNjEyLCBlbGFfcGxvdF9zd2QxMzE2KQoKZ2dwbG90KGVsYV9wbG90X3N3ZCwgYWVzKHggPSBDYXRlZ29yeSwgeSA9IFByb3BvcnRpb24sIGZpbGwgPSBmYWN0b3IoTGV2ZWxzLCBsZXZlbHMgPSBjKCJsZXZlbDRfcHJvcG9ydGlvbiIsICJsZXZlbDNfcHJvcG9ydGlvbiIsICJsZXZlbDJfcHJvcG9ydGlvbiIsICJsZXZlbDFfcHJvcG9ydGlvbiIpKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGZhY2V0X2dyaWQoeWVhcl9jYXQgfiBHcmFkZSkgKwogIGxhYnModGl0bGUgPSAiRUxBIFNjb3JlIExldmVscyBieSBEaXNhYmlsaXR5IG9yIE5vdCIsIHggPSAiRGlzYWJpbGl0eSBTdGF0dXMiLCB5ID0gIlByb3BvcnRpb24iLCBmaWxsID0gIkxldmVscyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKQpgYGAKTGlrZSB0aGUgcGhlbm9tZW5vbiBpbiBNYXRoLCBzdHVkZW50cyB3aXRoIGEgZGlzYWJpbGl0eShTV0QpIHBlcmZvcm1lZCBtdWNoIHdvcnNlIHRoYW4gc3R1ZGVudHMgd2l0aG91dCBhIGRpc2FiaWxpdHkuIE1vcmVvdmVyLCB3aGV0aGVyIHN0dWRlbnRzIHdlcmUgZGlzYWJsZWQgb3Igbm90LCB0aGVyZSB3ZXJlIGZld2VyIHN0dWRlbnRzIGluIGxldmVsNCBvZiBFTEEgdGhhbiBvZiBNYXRoLiBBbmQgc3R1ZGVudHMgd2l0aCBhIGRpc2FiaWxpdHkgYWNjb3VudGVkIGZvciB0aGUgaGlnaGVyIHByb3BvcnRpb24gb2YgbGV2ZWwxIGluIEVMQSBleGFtcyB0aGFuIGluIE1hdGggZXhhbXMuCgoKIyMjIGUpIE1hdGggU2NvcmUgQW5hbHlzaXMgYnkgRW5nbGlzaCBQcm9maWNpZW50IFN0YXR1cwoKIyMjIyBBbmFseXNpcyB3aXRoIGdyYWRlcywgeWVhciBncm91cCwgYW5kIEVMTCBDYXRlZ29yeSBvbiBzdGFjayBwbG90IApgYGB7cn0KI21hdGggRWxsKEVuZ2xpc2ggbGVhcm5lcikKcGxvdF9lbGwwNjEyIDwtIG1hdGhfZWxsXzA2MTIgJT4lCiAgZ3JvdXBfYnkoR3JhZGUsIENhdGVnb3J5KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShsZXZlbDFfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDEsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsMl9wcm9wb3J0aW9uID0gc3VtKGxldmVsMiwgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWwzX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwzLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDRfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDQsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSkpICAlPiUgCiAgZ2F0aGVyKExldmVscywgUHJvcG9ydGlvbiwgLUdyYWRlLCAtQ2F0ZWdvcnkpICU+JSAKICBtdXRhdGUoeWVhcl9jYXQgPSAiMDYtMTIiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gQ2F0ZWdvcnksIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gZmFjdG9yKExldmVscywgbGV2ZWxzID0gYygibGV2ZWw0X3Byb3BvcnRpb24iLCAibGV2ZWwzX3Byb3BvcnRpb24iLCAibGV2ZWwyX3Byb3BvcnRpb24iLCAibGV2ZWwxX3Byb3BvcnRpb24iKSkpKSArCiAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgIGZhY2V0X2dyaWQoeWVhcl9jYXQgfiBHcmFkZSkgKwogICBsYWJzKHRpdGxlID0gIk1hdGggU2NvcmUgTGV2ZWxzIHdpdGggcmVzcGVjdCB0byBFbmdsaXNoIFByb2ZpY2llbnQgU3RhdHVzIiwgeCA9ICJFbmdsaXNoIFByb2ZpY2llbnQgU3RhdHVzIiwgeSA9ICJQcm9wb3J0aW9uIiwgZmlsbCA9ICJMZXZlbHMiKSArCiAgICN0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQocmV2ZXJzZT1UUlVFKSkKCnBsb3RfZWxsMTMxNiA8LSBtYXRoX2VsbF8xMzE2ICU+JQogIGdyb3VwX2J5KEdyYWRlLCBDYXRlZ29yeSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2UobGV2ZWwxX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwxLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDJfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDIsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMywgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWw0X3Byb3BvcnRpb24gPSBzdW0obGV2ZWw0LCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpKSAgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjEzLTE2IikgJT4lIAogIGdncGxvdChhZXMoeCA9IENhdGVnb3J5LCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IGZhY3RvcihMZXZlbHMsIGxldmVscyA9IGMoImxldmVsNF9wcm9wb3J0aW9uIiwgImxldmVsM19wcm9wb3J0aW9uIiwgImxldmVsMl9wcm9wb3J0aW9uIiwgImxldmVsMV9wcm9wb3J0aW9uIikpKSkgKwogICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICBmYWNldF9ncmlkKHllYXJfY2F0IH4gR3JhZGUpICsKICAgbGFicyh4ID0gIkVuZ2xpc2ggUHJvZmljaWVudCBTdGF0dXMiLCB5ID0gIlByb3BvcnRpb24iLCBmaWxsID0gIkxldmVscyIpICsKICAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKSArCiAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0gMSkpCgpncmlkLmFycmFuZ2UocGxvdF9lbGwwNjEyLCBwbG90X2VsbDEzMTYsIG5yb3cgPSAyKQpgYGAKRmluYWxseSwgZm9yIEVMTCBhbmFseXNlcywgd2UgdG9vayBzdGFja2VkIGJhciBjaGFydHMgYmVjYXVzZSBpdCB3YXMgdGhlIGNsZWFyZXN0IHdheSB0byBjb21wYXJlIHdpdGhpbiBvdXIgZGF0YXNldC4gCgpBY2NvcmRpbmcgdG8gdGhlIHBsb3QgYWJvdmUsIHdlIGNvdWxkIGluZGljYXRlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBFbmdsaXNoIFByb2ZpY2llbnQgU3RhdHVzIGFuZCBzdHVkZW50cycgcGVyZm9ybWFuY2UgbGV2ZWwuCgoxLiBUaGUgZGVmaW5pdGlvbiBvZiBFTEwsIEVQLCBGb3JtZXIgRUxMOgpFTEw6IEVuZ2xpc2gtTGFuZ3VhZ2UgTGVhcm5lci4gIkFuIEVuZ2xpc2ggbGFuZ3VhZ2UgbGVhcm5lciAob2Z0ZW4gY2FwaXRhbGl6ZWQgYXMgRW5nbGlzaCBMYW5ndWFnZSBMZWFybmVyIG9yIGFiYnJldmlhdGVkIHRvIEVMTCkgaXMgYSBwZXJzb24gd2hvIGlzIGxlYXJuaW5nIHRoZSBFbmdsaXNoIGxhbmd1YWdlIGluIGFkZGl0aW9uIHRvIGhpcyBvciBoZXIgbmF0aXZlIGxhbmd1YWdlLiIgKFdpa2lwZWRpYSkKRVA6IFBlb3BsZSB3aXRoIEVuZ2xpc2ggUHJvZmljaWVudCBhcmUgdGhvc2Ugd2hvIHRha2UgRW5nbGlzaCBhcyBtb3RoZXIgdG9uZ3VlLgpGb3JtZXIgRUxMOiBGb3JtZXIgRW5nbGlzaCBMYW5ndWFnZSBMZWFybmVycy4gIkZvcm1lciBFbmdsaXNoIExhbmd1YWdlIExlYXJuZXJzIGluY2x1ZGVzIGFueSBzdHVkZW50cyB3aG8gd2VyZSBjbGFzc2lmaWVkIGFzIEVuZ2xpc2ggTGFuZ3VhZ2UgTGVhcm5lcnMgaW4gYXQgbGVhc3Qgb25lIG9mIHRoZSBwcmV2aW91cyB0d28gc2Nob29sIHllYXJzLiIgKE9mZmljaWFsIE5vdGVzIGZvciB0aGlzIGRhdGFzZXQpCgoyLiBXZSBjb3VsZCBmaW5kIHRoYXQgc3R1ZGVudHMgaW4gRUxMIGdyb3VwIHBlcmZvcm1lZCBtdWNoIHdvcnNlIHRoYW4gRVAgZ3JvdXBzIHRocm91Z2ggeWVhcnMgMjAwNiB0byAyMDE2LiBJbiB5ZWFycyAyMDEzIHRvIDIwMTYsIG9mZmljaWFsIGVkdWNhdGlvbiBkZXBhcnRtZW50IGFkZGVkIGEgbmV3IGNsYXNzIGZvciBFbmdsaXNoIFByb2ZpY2llbnQgU3RhdHVzIGFzICJGb3JtZXIgRUxMIi4gV2UgY291bGQgZmluZCB0aGF0IGV4Y2VwdCBmb3IgZ3JhZGUzLCBzdHVkZW50cyBpbiBGb3JtZXIgRUxMIGdyb3VwIHBlcmZvcm1lZCBiZXR0ZXIgdGhhbiBFTEwgYW5kIHNsaWdodGx5IHdvcnNlIHRoYW4gRVAsIHdoaWNoIG1pZ2h0IGluZGljYXRlIHRoYXQgYmV0dGVyIEVuZ2xpc2ggTGFuZ3VhZ2UgYWJpbGl0eSBpbXByb3ZlZCBzdHVkZW50cycgdW5kZXJzdGFuZGluZyBvZiBtYXRoLgoKYGBge3J9CiMgRUxBIEVsbChFbmdsaXNoIGxlYXJuZXIpCmVsYV9wbG90X2VsbDA2MTIgPC0gZWxhX2VsbF8wNjEyICU+JQogIGdyb3VwX2J5KEdyYWRlLCBDYXRlZ29yeSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2UobGV2ZWwxX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwxLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDJfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDIsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMywgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWw0X3Byb3BvcnRpb24gPSBzdW0obGV2ZWw0LCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpKSAgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjA2LTEyIikgJT4lIAogIGdncGxvdChhZXMoeCA9IENhdGVnb3J5LCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IGZhY3RvcihMZXZlbHMsIGxldmVscyA9IGMoImxldmVsNF9wcm9wb3J0aW9uIiwgImxldmVsM19wcm9wb3J0aW9uIiwgImxldmVsMl9wcm9wb3J0aW9uIiwgImxldmVsMV9wcm9wb3J0aW9uIikpKSkgKwogICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICBmYWNldF9ncmlkKHllYXJfY2F0IH4gR3JhZGUpICsKICAgbGFicyh0aXRsZSA9ICJFTEEgU2NvcmUgTGV2ZWxzIHdpdGggcmVzcGVjdCB0byBFbmdsaXNoIFByb2ZpY2llbnQgU3RhdHVzIiwgeCA9ICJFbmdsaXNoIFByb2ZpY2llbnQgU3RhdHVzIiwgeSA9ICJQcm9wb3J0aW9uIiwgZmlsbCA9ICJMZXZlbHMiKSArCiAgICN0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQocmV2ZXJzZT1UUlVFKSkKCmVsYV9wbG90X2VsbDEzMTYgPC0gZWxhX2VsbF8xMzE2ICU+JQogIGdyb3VwX2J5KEdyYWRlLCBDYXRlZ29yeSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2UobGV2ZWwxX3Byb3BvcnRpb24gPSBzdW0obGV2ZWwxLCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpLCBsZXZlbDJfcHJvcG9ydGlvbiA9IHN1bShsZXZlbDIsIG5hLnJtID0gVFJVRSkvc3VtKE51bWJlcl9UZXN0ZWQsIG5hLnJtID0gVFJVRSksIGxldmVsM19wcm9wb3J0aW9uID0gc3VtKGxldmVsMywgbmEucm0gPSBUUlVFKS9zdW0oTnVtYmVyX1Rlc3RlZCwgbmEucm0gPSBUUlVFKSwgbGV2ZWw0X3Byb3BvcnRpb24gPSBzdW0obGV2ZWw0LCBuYS5ybSA9IFRSVUUpL3N1bShOdW1iZXJfVGVzdGVkLCBuYS5ybSA9IFRSVUUpKSAgJT4lIAogIGdhdGhlcihMZXZlbHMsIFByb3BvcnRpb24sIC1HcmFkZSwgLUNhdGVnb3J5KSAlPiUgCiAgbXV0YXRlKHllYXJfY2F0ID0gIjEzLTE2IikgJT4lIAogIGdncGxvdChhZXMoeCA9IENhdGVnb3J5LCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IGZhY3RvcihMZXZlbHMsIGxldmVscyA9IGMoImxldmVsNF9wcm9wb3J0aW9uIiwgImxldmVsM19wcm9wb3J0aW9uIiwgImxldmVsMl9wcm9wb3J0aW9uIiwgImxldmVsMV9wcm9wb3J0aW9uIikpKSkgKwogICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICBmYWNldF9ncmlkKHllYXJfY2F0IH4gR3JhZGUpICsKICAgbGFicyh4ID0gIkVuZ2xpc2ggUHJvZmljaWVudCBTdGF0dXMiLCB5ID0gIlByb3BvcnRpb24iLCBmaWxsID0gIkxldmVscyIpICsKICAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChyZXZlcnNlPVRSVUUpKSArCiAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0gMSkpCgpncmlkLmFycmFuZ2UoZWxhX3Bsb3RfZWxsMDYxMiwgZWxhX3Bsb3RfZWxsMTMxNiwgbnJvdyA9IDIpCgpgYGAKQWNjb3JkaW5nIHRvIHRoZSBwbG90IGFib3ZlLCB3ZSBjb3VsZCBpbmRpY2F0ZSB0aGF0IHRoZSBwcm9maWNpZW5jeSBvZiBFbmdsaXNoIGhhZCBhIGxhcmdlciBpbXBhY3Qgb24gRUxBIHNjb3JlcyB0aGFuIE1hdGggc2NvcmVzLiBTdHVkZW50cyBpbiBFTEwgY2F0ZWdvcnkgcGVyZm9ybWVkIG11Y2ggd29yc2UgdGhhbiBzdHVkZW50cyBpbiBFUCBhbmQgZm9ybWVyIEVMTCBjYXRlZ29yaWVzLiBIb3dldmVyLCBhY2NvcmRpbmcgdG8gdGhlIGRlZmluaXRpb24gb2YgIkZvcm1lciBFbGwiLCB3ZSBpbmZlcnJlZCB0aGF0IHN0dWRlbnRzIGNvdWxkIHF1aWNrbHkgYWRhcHQgdG8gRW5nbGlzaCBzdHVkeSBlbnZpcm9ubWVudCBhcyBhIGZvcm1lciBFTEwgaW4gb25lIHRvIHR3byB5ZWFycywgYW5kIGltcHJvdmUgdGhlaXIgYWNhZGVtaWMgcGVyZm9ybWFuY2VzLgoKIyMgKDMpIEhpZ2ggU2Nob29sIFN0dWRlbnQgUGVyZm9ybWFuY2VzIEFuYWx5c2lzCgojIyMgYSkgT3ZlcmFsbCBHcmFkdWF0aW9uIFJhdGUgYW1vbmcgRGlzdHJpY3RzCmBgYHtyLCBldmFsID0gRkFMU0V9CmNvbF9uYW1lczwtYygiRGlzdHJpY3QiLCJDYXRlZ29yeSIsICJDb2hvcnRfWWVhciIsICJDb2hvcnQiLCAibnVtX2NvaG9ydCIsICJudW1fZ3JhZHMiLCAicGVyX2dyYWRzX2NvaG9ydCIsICJudW1fcmVnZW50cyIsICJwZXJfcmVnZW50c19jb2hvcnQiLCAicGVyX3JlZ2VudHNfZ3JhZHMiLCAibnVtX2FkcmVnZW50cyIsICJwZXJfYWRyZWdlbnRzX2NvaG9ydCIsICJwZXJfYWRyZWdlbnRzX2dyYWRzIiAsICJudW1fd2FkcmVnZW50cyIsICAgInBlcl93YWRyZWdlbnRzX2NvaG9ydCIsICJwZXJfd2FkcmVnZW50c19ncmFkcyIsIm51bV9sb2NhbCIsInBlcl9sb2NhbF9jb2hvcnQiLCJwZXJfbG9jYWxfZ3JhZHMiLCJudW1fZW5yb2xsZWQiLCJwZXJfZW5yb2xsZWRfY29ob3J0IiwibnVtX2Ryb3BvdXQiLCJwZXJfZHJvcG91dF9jb2hvcnQiLCJudW1fU0FDQyIsInBlcl9TQUNDX2NvaG9ydCIsIm51bV9UQVNDIiwicGVyX1RBU0dfY29ob3J0IikKZ3JhZHVhdGU8LXJlYWQuY3N2KCIyMDE2IEdyYWR1YXRpb25fUmF0ZXNfUHVibGljX0Rpc3RyaWN0X0FMTC5jc3YiLHNraXA9OCxjb2wubmFtZXMgPWNvbF9uYW1lcykKIyByZW1vdmUgdW5lY2Vzc2FyeSBmZWF0dXJlcwpncmFkdWF0ZTwtZ3JhZHVhdGVbLTJdCmNvbHM8LWNvbF9uYW1lc1s2OjI3XQojIHN0YW5kYXJkaXplIG1pc3NpbmcgZGF0YSAKZ3JhZHVhdGVbZ3JhZHVhdGUgPT0gInMiXSA9IE5BCiMgdHJhbnNmb3JtIHRoZSBmYXRvciBpbnRvIG51bWVyaWMgCmdyYWR1YXRlWyxjb2xzXSA8LSBhcHBseShncmFkdWF0ZVssY29sc10sIDIsIGZ1bmN0aW9uKHgpIGFzLm51bWVyaWMoeCkpCmBgYApGaXJzdCBhbmQgZm9yZW1vc3QsIHdlIGhhZCB0byBkbyBkYXRhIGNsZWFuaW5nIGFuZCBwcmVwcm9jZXNzaW5nIHRvIHRoZSBkYXRhIHNldCBpbiBvcmRlciB0byBhbmFseXplIHRoZSBkYXRhLiBBcyB0aGUgZm9ybWF0IG9mIHRoZSBkYXRhIGZyYW1lIHdhcyBhIGxpdHRsZSBtZXNzeSB3aGVuIGl0IHdhcyBmaXJzdCBpbXBvcnRlZCB0byBSU3R1ZGlvLCB3ZSBnb3QgdG8gcmVhcnJhbmdlIHRoZSBkYXRhIHNldCByZWxhdGVkIHRvIHRoZSBncmFkdWF0aW9uIGluZm9ybWF0aW9uLCBzdWNoIGFzIHJlbmFtaW5nIHRoZSBjb2x1bW4gbmFtZXMsIHJlbW92aW5nIHRoZSB1bm5lY2Vzc2FyeSBmZWF0dXJlcywgc3RhbmRhcmRpemluZyBtaXNzaW5nIGRhdGEgYW5kIHRyYW5zZm9ybWluZyB0aGUgZGF0YSB0eXBlIG9mIHRoZSBncmFkdWF0aW9uIGluZGljYXRvcnMgZnJvbSBmYWN0b3IgaW50byBudW1lcmljLgpgYGB7cn0KIyNyZW1vdmUgdGhlIG1pc3NpbmcgZGF0YSBpbiBwZXJfZ3JhZHNfY29ob3J0CmdyYWR1YXRlIDwtIGdyYWR1YXRlW2NvbXBsZXRlLmNhc2VzKGdyYWR1YXRlKSxdCmdyYWR1YXRlIDwtIGdyYWR1YXRlJT4lIGZpbHRlcihEaXN0cmljdCE9NzkpCiAgCmdyYWR1YXRlX3BlcjwtIGdyYWR1YXRlJT4lCiAgICBncm91cF9ieShEaXN0cmljdCwgQ29ob3J0X1llYXIpICU+JSAKICAgIyBkcGx5cjo6c3VtbWFyaXNlKG51bV9ncmFkcz0gc3VtKG51bV9jb2hvcnQpKQogICAgIGRwbHlyOjpzdW1tYXJpc2Uoc3VtX3Blcl9ncmFkPSBzdW0obnVtX2dyYWRzKS9zdW0obnVtX2NvaG9ydCkpCmBgYApGcm9tIHRoZSBtaXNzaW5nIGRhdGEgZ3JhcGgsIHdlIGZvdW5kIG91dCB0aGF0IGEgZmV3IG9ic2VydmF0aW9ucyBhcmUgbWlzc2luZyBvbiBhbGwgaW5jbHVkZWQgdmFyaWFibGVzLiBPZnRlbiwgdGhpcyBpbmRpY2F0ZXMgYSBtb3JlIGNvbXBsaWNhdGVkIG1vZGVsIGlzIG5lZWRlZCBmb3IgdGhpcyBtaXNzaW5nbmVzcyBtZWNoYW5pc20sIGJ1dCB3ZSBkZWNpZGVkIHRvIHJlbW92ZSBhbGwgdGhlIG1pc3Npbmcgb2JzZXJ2YXRpb25zIHNpbmNlIHRoZSBudW1iZXIgb2YgbWlzc2luZyBvYnNlcnZhdGlvbnMgd2FzIHJhdGhlciBzbWFsbCBjb21wYXJlZCB0byB0aGUgdG90YWwgZGF0YSBzZXQuCgpCZXNpZGVzLCB3ZSBmb3VuZCBvdXQgdGhlcmUgd2FzIGFuIGV4dHJhIGRpc3RyaWN0IDc5LCBOZXcgWW9yayBDaXR5J3MgQWx0ZXJuYXRpdmUgU2Nob29scyBEaXN0cmljdCwgaW5jbHVkZWQgaW4gdGhlIGRhdGEgc2V0LiBTaW5jZSBpdCB3YXMgbm90IHRoZSBmb2N1cyBvZiBvdXIgcmVzZWFyY2gsIHdlIGRlY2lkZWQgdG8gZHJvcCB0aGUgb2JzZXJ2YXRpb25zIG9mIERpc3RyaWN0IDc5IHRvIGF2b2lkIHRoZSBpbmZsdWVuY2UuCgojIyMjIChpKSBIZWF0bWFwIG9mIHRoZSBHcmFkdWF0aW9uIFJhdGUgYW1vbmcgRGlzdHJpY3RzCgpgYGB7cixldmFsID0gRkFMU0V9CgpncmFkdWF0ZV9wZXIkRGlzdHJpY3QgPC0gZmFjdG9yKGdyYWR1YXRlX3BlciREaXN0cmljdCkgICAgIAoKZ2dwbG90KGdyYWR1YXRlX3BlciwgYWVzKENvaG9ydF9ZZWFyLCBEaXN0cmljdCwgZmlsbCA9IHN1bV9wZXJfZ3JhZCkpICsgCiAgICBnZW9tX3RpbGUoKSArCiAgICMgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9cm91bmQoc3VtX3Blcl9ncmFkLDMpKSwgY29sb3IgPSAid2hpdGUiLHNpemU9MykgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDAxLCAyMDEyLCAxKSkrCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT0xMCkpKwogICAgc2NhbGVfZmlsbF92aXJpZGlzKCkrCiAgICBsYWJzKHRpdGxlID0gIlRoZSBncmFkdWF0aW9uIHJhdGUgb2YgZGlmZmVyZW50IGRpc3RyaWN0cyBmcm9tIDIwMDEgdG8gMjAxMiIseD0iQ29ob3J0IFllYXIiLCBmaWxsPSJHcmFkdWF0aW9uIFJhdGUiKQoKCmBgYAoKQWZ0ZXIgdGhlIHByb2Nlc3Mgb2YgZGF0YSBjbGVhbnNpbmcsIHdlIGF0dGVtcHRlZCB0byBkZW1vbnN0cmF0ZSB0aGUgZ3JhZHVhdGlvbiByYXRlcyBvZiBhbGwgc3R1ZGVudHMgYW1vbmcgdGhlIDMyIGRpc3RyaWN0cy4gQWNjb3JkaW5nIHRvIHRoZSBkYXRhc2V0LCB0aGUgY29ob3J0IGNvbnNpc3RzIG9mIGFsbCBzdHVkZW50cyB3aG8gZmlyc3QgZW50ZXJlZCA5dGggZ3JhZGUgaW4gYSBnaXZlbiBzY2hvb2wgeWVhciAoZS5nLiB0aGUgQ29ob3J0IG9mIDIwMDYgZW50ZXJlZCA5dGggZ3JhZGUgaW4gdGhlIDIwMDYtMjAwNyBzY2hvb2wgeWVhcikuICBHcmFkdWF0ZXMgYXJlIGRlZmluZWQgYXMgdGhvc2Ugc3R1ZGVudHMgZWFybmluZyBlaXRoZXIgYSBMb2NhbCBvciBSZWdlbnRzIGRpcGxvbWEuIEZyb20gdGhlIGhlYXRtYXAsIHdlIGZvdW5kIG91dCB0aGF0IHRoZSB0d28gZGlzdHJpY3RzIHdpdGggdGhlIGJlc3QgZ3JhZHVhdGlvbiByYXRlIHdlcmUgRGlzdHJpY3QgMjYgYW5kIERpc3RyaWN0IDEzLCBhbmQgdGhlIGRpc3RyaWN0cyB3aXRoIHRoZSBkZWNlbnQgZ3JhZHVhdGlvbiByYXRlcyB3ZXJlIDI4LCAyMiBhbmQgNC4gT24gdGhlIG90aGVyIGhhbmQsIHRoZSBncmFkdWF0aW9uIHJhdGUgb2YgRGlzdHJpY3QgMjMsIDE2IGFuZCA4IHdhcyB0aGUgbG93ZXN0LCBlc3BlY2lhbGx5IERpc3RyaWN0IDIzIHdoZXJlIHRoZSByYXRlIHdhcyBkZWNyZWFzaW5nIGFmdGVyIDIwMDQgd2hpbGUgdGhlIHJhdGUgb2Ygb3RoZXIgZGlzdHJpY3RzIHdhcyBtb3N0bHkgZ3JhZHVhbGx5IHJhaXNpbmcuCgpBcyB3ZSBoYXZlIGtub3duLCBEaXN0cmljdCAyMyBpcyBvbmUgb2YgdGhlIHNtYWxsZXN0IGluIHRoZSBjaXR5LCB3aGljaCBzZXJ2ZXMgT2NlYW4gSGlsbCwgQnJvd25zdmlsbGUsIGFuZCBwYXJ0cyBvZiBFYXN0IE5ldyBZb3JrLCBhbmQgaW5jbHVkZXMgc29tZSBvZiB0aGUgY2l0eSdzIHBvb3Jlc3QgbmVpZ2hib3Job29kcy4gU2luZ2xlLWZhbWlseSBob21lcyBhcmUgaW50ZXJzcGVyc2VkIHdpdGggb2xkIGJyb3duc3RvbmVzLCBhcGFydG1lbnQgYnVpbGRpbmdzLCBsYXJnZSBwdWJsaWMgaG91c2luZyBwcm9qZWN0cyBhbmQgaG9tZWxlc3Mgc2hlbHRlcnMuIFRoZSBncmFkdWF0aW9uIHJhdGUgc2hvd24gYnkgdGhlIGdyYXBoIHNlZW1zIHRvIG1hdGNoIHdpdGggdGhlIGVkdWNhdGlvbiBjb25kaXRpb24gb2YgdGhlIGRpc3RyaWN0cy4KCkZyb20gdGhlIHdlYnNpdGUgKGh0dHA6Ly9pbnNpZGVzY2hvb2xzLm9yZy9kaXN0cmljdHMvYnJvb2tseW4vZGlzdHJpY3QtMjMpLCB0aGUgc2Nob29scywgYW1vbmcgdGhlIGxvd2VzdC1wZXJmb3JtaW5nIGluIHRoZSBjaXR5LCBoYXZlIGJlZW4gbG9zaW5nIHBvcHVsYXRpb24sIHBhcnRseSBhcyBhIHJlc3VsdCBvZiBjb21wZXRpdGlvbiBmcm9tIGNoYXJ0ZXIgc2Nob29scy4gVGhlIENvbW11bml0eSBFZHVjYXRpb24gQ291bmNpbCB2b3RlZCBpbiAyMDEzIHRvIGRvIGF3YXkgd2l0aCB6b25lZCBzY2hvb2xzLCBhbGxvd2luZyBwYXJlbnRzIHRvIGFwcGx5IHRvIGFueSBzY2hvb2wgaW4gdGhlIGRpc3RyaWN0LiBIb3dldmVyLCBwYXJlbnRzIGNvbXBsYWluZWQgdGhhdCB0aGVyZSB3ZXJlIGZldyB2aWFibGUgY2hvaWNlcy4KCiMjIyMgKGlpKSBJbmRpY2F0b3JzIG9mIERpc3RyaWN0cyB3aXRoIHRoZSBCZXN0IGFuZCBXb3JzdCBPdmVyYWxsIEdyYWR1YXRpb24gUmF0ZQpgYGB7cn0KZ3JhZHVhdGVfdGlkeTwtIGdyYWR1YXRlJT4lCiAgICBncm91cF9ieShEaXN0cmljdCxDb2hvcnRfWWVhcikgJT4lIAogICAgZHBseXI6OnN1bW1hcmlzZShzdW1fcGVyX2dyYWQ9IHN1bShudW1fZ3JhZHMpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9kcm9wb3V0PSBzdW0obnVtX2Ryb3BvdXQpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9yZWdlbnQ9c3VtKG51bV9yZWdlbnRzKSAvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX2FkcmVnZW50PSBzdW0obnVtX2FkcmVnZW50cykgL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl93YWRyZWdlbnQ9IHN1bShudW1fd2FkcmVnZW50cykvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX2xvY2FsID0gc3VtKG51bV9sb2NhbCkvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3NhY2M9IHN1bShudW1fU0FDQykvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3Rhc2M9IHN1bShudW1fVEFTQykvc3VtKG51bV9jb2hvcnQpKQpncmFkdWF0ZV90aWR5JERpc3RyaWN0IDwtIGZhY3RvcihncmFkdWF0ZV90aWR5JERpc3RyaWN0KQoKb3JkZXJjbGFzcyA8LSBncmFkdWF0ZSU+JQogICAgICAgICAgICAgZ3JvdXBfYnkoRGlzdHJpY3QpICU+JSAKICAgICAgICAgICAgIGRwbHlyOjpzdW1tYXJpc2Uoc3VtX3Blcl9ncmFkPSBzdW0obnVtX2dyYWRzKS9zdW0obnVtX2NvaG9ydCkpCm9yZGVyY2xhc3NfYmVzdCA8LSBvcmRlcmNsYXNzIFtvcmRlcigtb3JkZXJjbGFzcyRzdW1fcGVyX2dyYWQpLF1bMTozLF0Kb3JkZXJjbGFzc193b3JzdCA8LSBvcmRlcmNsYXNzIFtvcmRlcihvcmRlcmNsYXNzJHN1bV9wZXJfZ3JhZCksXVsxOjMsXQpncmFkdWF0ZV90aWR5MSA8LSB3aXRoaW4oZ3JhZHVhdGVfdGlkeSx7CiAgY2F0PC1OQQogIGNhdFtEaXN0cmljdCAlaW4lIG9yZGVyY2xhc3NfYmVzdCREaXN0cmljdCBdPC0iYmVzdCIKICBjYXRbRGlzdHJpY3QgJWluJSBvcmRlcmNsYXNzX3dvcnN0JERpc3RyaWN0IF08LSJ3b3JzdCIKICBjYXRbaXMubmEoY2F0KV08LSJub3JtYWwiCn0KKQpncmFkdWF0ZV90aWR5MTwtZ3JhZHVhdGVfdGlkeTElPiVmaWx0ZXIoY2F0ICE9J25vcm1hbCcpCmdyYWR1YXRlX3RpZHkxJGNhdCA8LSBmYWN0b3IoZ3JhZHVhdGVfdGlkeTEkY2F0LCBsYWJlbHMgPSAgYygiYmVzdCIsIndvcnN0IikpCmBgYAoKQWZ0ZXIgZGF0YSBwcmVwcm9jZXNzaW5nLCB0aGVyZSB3YXMgYW5vdGhlciBjaGFsbGVuZ2Ugb2YgZGF0YSBwcm9jZXNzaW5nIHdlIGZhY2VkLiBXZSBhdHRlbXB0ZWQgdG8gZGVtb25zdHJhdGUgdGhlIG92ZXJhbGwgZ3JhZHVhdGlvbiByYXRlcyBvZiBhbGwgZGlzdHJpY3RzIG92ZXIgdGhlIHllYXJzLCBidXQgdGhlIG51bWJlciBvZiBkaXN0cmljdHMgd2FzIGEgYml0IHRvbyBsYXJnZSBmb3IgcHJlc2VudGF0aW9uLiBUaHVzLCB3ZSB0cmllZCB0byBzZWxlY3QgdGhlIHRocmVlIGRpc3RyaWN0cyB3aXRoIHRoZSBiZXN0IGdyYWR1YXRpb24gcmF0ZSBhbmQgdGhyZWUgd2l0aCB0aGUgd29yc3Qgb25lLiAKClRvIGF0dGFpbiB0aGlzIGdvYWwsIHdlIGNyZWF0ZWQgYSBkYXRhIGZyYW1lIGNhbGxlZCAib3JkZXJjbGFzcyIgd2hpY2ggY29udGFpbnMgdGhlIG92ZXJhbGwgZ3JhZHVhdGlvbiByYXRlIGdyb3VwZWQgYnkgZGlzdHJpY3QsIHRoZW4gZGVyaXZlIHRoZSB0aHJlZSBiZXN0IGFuZCB0aHJlZSB3b3JzdCByZWNvcmRzIGZyb20gdGhhdCBpbiBvcmRlciB0byBhZGQgYSBuZXcgZmVhdHVyZSAiY2F0IiB0byB0aGUgcHJvY2Vzc2VkIGRhdGFzZXQgd2l0aCB0aGUgcHVycG9zZSBvZiBpbmRpY2F0aW5nIHRoZSBjYXRlZ29yeSBvZiB0aGUgZGlzdHJpY3RzIHNldCB1cCBieSBvdXJzZWx2ZXMuCgoKYGBge3IsZmlnLndpZHRoPTEwLGZpZy5oZWlnaHQ9MTB9CgpncmFkdWF0ZV90aWR5MSREaXN0cmljdDwtZmFjdG9yKGdyYWR1YXRlX3RpZHkxJERpc3RyaWN0LGxldmVscz1jKDI2LDIzLDEzLDE2LDI4LDE4KSkKdG9fc3RyaW5nPC1hc19sYWJlbGxlcihjKCcxJz0nZGlzdHJpY3QyNicsJzInPSdkaXN0cmljdDIzJywnMyc9J2Rpc3RyaWN0MTMnLCc0Jz0nZGlzdHJpY3QxNicsJzUnPSdkaXN0cmljdDI4JywnNic9J2Rpc3RyaWN0MTgnKSkKCmdsYWJlbDwtYygnR3JhZHVhdGlvbiBSYXRlJywnRHJvcG91dCBSYXRlJywnUmVnZW50IFJhdGUnLCdBZHZhbmNlZCBSZWdlbnQgUmF0ZScsJ1dpdGhvdXQgQWR2YW5jZWQgUmVnZW50IFJhdGUnLCdMb2NhbCBSYXRlJywnU0FDQyBSYXRlJywnVEFTQyBSYXRlJykKZ2dwYXJjb29yZChncmFkdWF0ZV90aWR5MSwgY29sdW1ucyA9MzoxMCxzY2FsZT0iZ2xvYmFsbWlubWF4Iixncm91cENvbHVtbiA9ICJjYXQiLGFscGhhTGluZXMgPSAwLjMpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTAsYW5nbGU9MjApKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1nbGFiZWwpKwogIGxhYnModGl0bGU9IkluZGljYXRvcnMgb2YgU2l4IERpc3RyaWN0cyB3aXRoIHRoZSBCZXN0IGFuZCBXb3JzdCBPdmVyYWxsIEdyYWR1YXRpb24gUmF0ZSAiLGNvbD0nQmVzdC9Xb3JzdCcpICsKICBmYWNldF93cmFwKH5EaXN0cmljdCxzY2FsZXM9J2ZpeGVkJyxucm93PTMsbGFiZWxsZXI9dG9fc3RyaW5nKQoKYGBgCldlIGFwcGxpZWQgcGFyYWxsZWwgY29vcmRpbmF0ZSB0byBhbmFseXplIHRoZSBwYXR0ZXJucyBvZiBncmFkdWF0aW9uIGluZGljYXRvcnMgb24gZGlzdHJpY3RzIHdpdGggdGhlIGJlc3QgYW5kIHRoZSB3b3JzdCBvdmVyYWxsIGdyYWR1YXRpb24gcmF0ZS4gVGhlIG11bHRpcGxlIGxpbmVzIGZvciBlYWNoIGdyaWQgcmVmZXIgdG8gdGhlIHJhdGVzIGZvciBlYWNoIHllYXIuCgpGb3IgdGhlIGRpc3RyaWN0cyB3aXRoIHRoZSBiZXN0IGdyYWR1YXRpb24gcmF0ZXMsIHdlIGZvdW5kIG91dCB0aGF0IHRoZXJlIHdhcyBhIHNpbWlsYXIgcGF0dGVybiBzaGFyZWQgYnkgdGhlIGRpc3RyaWN0cyAtLSB0aGV5IGFsbCBnb3QgYSByZWxhdGl2ZWx5IGxvdyBkcm9wb3V0IHJhdGUsIGxvdyBMb2NhbCBkaXBsb21hIHBlcmNlbnRhZ2UsIGxvdyBTQUNDIHBlcmNlbnRhZ2UsIGxvdyBUQVNDIHBlcmNlbnRhZ2UgYW5kIGhpZ2ggUmVnZW50IHBlcmNlbnRhZ2UuIEVzcGVjaWFsbHkgZm9yIERpc3RyaWN0IDI2IGFuZCAxMywgdGhleSBnb3QgYSBoaWdoIHJhdGUgb2YgQWR2YW5jZWQgUmVnZW50IERpcGxvbWEgYW5kIGxvdyByYXRlIG9mIFJlZ2VudCB3aXRob3V0IEFkdmFuY2VkIG92ZXIgdGhlIHllYXJzLgoKRm9yIHRoZSB0aHJlZSBkaXN0cmljdHMgd2l0aCB0aGUgd29yc3QgZ3JhZHVhdGlvbiByYXRlcywgdGhlIGRyb3BvdXQgcmF0ZSBpcyByZWxhdGl2ZWx5IGhpZ2ggYW5kIHRoZSBBZHZhbmNlZCBSZWdlbnQgcmF0ZSBpcyByZWxhdGl2ZWx5IGxvdy4gVGhlcmUgd2VyZSBmbHVjdHVhdGlvbnMgZXhpc3RlbnQgb3ZlciB0aGUgaW5kaWNhdG9ycyBSZWdlbnQgcmF0ZSwgdGhlIHJhdGUgb2YgUmVnZW50IHdpdGhvdXQgQWR2YW5jZWQgYW5kIExvY2FsIHJhdGUgYW1vbmcgdGhlIHllYXJzLCBlc3BlY2lhbGx5IGZvciBEaXN0cmljdCAxOCwgd2hlcmUgd2UgY291bGQgc2VlIHRoZXJlIHdlcmUgYWxtb3N0IHR3byBwYXR0ZXJucyBvdmVyIHRoZSBtZW50aW9uZWQgdGhyZWUgaW5kaWNhdG9ycy4gCgpXZSB3b3VsZCBleHBsYWluIHRoZSBtZWFuaW5nIG9mIHRoZSBpbmRpY2F0b3JzIHJlbGF0ZWQgdG8gZ3JhZHVhdGlvbi4KTmV3IFlvcmsgU3RhdGUgaGFzIHNlbGVjdGVkIGEgbmV3IGhpZ2ggc2Nob29sIGVxdWl2YWxlbmN5IHRlc3QgY2FsbGVkIHRoZSBUZXN0IEFzc2Vzc2luZyBTZWNvbmRhcnkgQ29tcGxldGlvbiAoVEFTQykgdG8gcmVwbGFjZSB0aGUgR2VuZXJhbCBFZHVjYXRpb25hbCBEZXZlbG9wbWVudCAoR0VEKSBhcyB0aGUgcHJpbWFyeSBwYXRod2F5IHRvIGEgTmV3IFlvcmsgU3RhdGUgSGlnaCBTY2hvb2wgRXF1aXZhbGVuY3kgRGlwbG9tYSBlZmZlY3RpdmUgSmFudWFyeSAyLCAyMDE0LiBUaGUgVEFTQyBpcyBhIHNlY3VyZSwgcmVsaWFibGUgYW5kIHZhbGlkIGluc3RydW1lbnQgdGhhdCBpcyB1c2VkIHRvIHZlcmlmeSB0aGF0IGV4YW1pbmVlcyBoYXZlIGtub3dsZWRnZSBpbiBjb3JlIGNvbnRlbnQgYXJlYXMgZXF1aXZhbGVudCB0byB0aGF0IG9mIGdyYWR1YXRpbmcgaGlnaCBzY2hvb2wgc2VuaW9ycy4KClRoZSBTa2lsbHMgJiBBY2hpZXZlbWVudCBDb21tZW5jZW1lbnQgQ3JlZGVudGlhbCAoU0FDQykgaXMgYSBjZXJ0aWZpY2F0ZSBhdmFpbGFibGUgb25seSB0byBzdHVkZW50cyB3aXRoIHNldmVyZSBjb2duaXRpdmUgZGlzYWJpbGl0aWVzIHdobyBhcmUgZWxpZ2libGUgdG8gdGFrZSB0aGUgTllTQUEgYW5kIGhhdmUgYXR0ZW5kZWQgc2Nob29sIGZvciBub3QgbGVzcyB0aGFuIDEyIHllYXJzLCBleGNsdWRpbmcgS2luZGVyZ2FydGVuLiBUaGUgQ2FyZWVyIERldmVsb3BtZW50IGFuZCBPY2N1cGF0aW9uYWwgU3R1ZGllcyAoQ0RPUykgQ29tbWVuY2VtZW50IENyZWRlbnRpYWwsIHdoaWNoIGluZGljYXRlcyB0aGF0IHRoZSBzdHVkZW50IGhhcyB0aGUga25vd2xlZGdlIGFuZCBza2lsbHMgbmVjZXNzYXJ5IGZvciBlbnRyeS1sZXZlbCBlbXBsb3ltZW50LiAKCkluIHRlcm1zIG9mIHRoZSBMb2NhbCBEaXBsb21hLCBhbGwgc3R1ZGVudHMgY2FuIGVhcm4gYSBSZWdlbnRzIG9yIEFkdmFuY2VkIFJlZ2VudHMgZGlwbG9tYTsgaG93ZXZlciwgb25seSBzdHVkZW50cyB3aG8gbWVldCBzcGVjaWZpYyBjcml0ZXJpYSBhcmUgZWxpZ2libGUgdG8gZ3JhZHVhdGUgd2l0aCBhIGxvY2FsIGRpcGxvbWEsIHdoaWNoIGFsbG93cyBzdHVkZW50cyB0byBncmFkdWF0ZSB3aXRoIGxvd2VyIGV4YW0gc2NvcmVzLiBCZXNpZGVzLCBhbiBBZHZhbmNlZCBSZWdlbnRzIGRpcGxvbWEgbGV0cyBzdHVkZW50cyBkZW1vbnN0cmF0ZSBhZGRpdGlvbmFsIHNraWxscyBpbiBtYXRoLCBzY2llbmNlLCBhbmQgbGFuZ3VhZ2VzIG90aGVyIHRoYW4gRW5nbGlzaC4KCgojIyMgYikgR3JhZHVhdGlvbiBSYXRlIEFuYWx5c2lzIGJ5IEVuZ2xpc2ggTGV2ZWwKYGBge3J9CmdyYWR1YXRlX2VsbDwtcmVhZC5jc3YoIjIwMTYgR3JhZHVhdGlvbl9SYXRlc19QdWJsaWNfRGlzdHJpY3RfRUxMLmNzdiIsc2tpcD04LGNvbC5uYW1lcyA9Y29sX25hbWVzKQpjb2xzPC1jb2xfbmFtZXNbNjoyN10KZ3JhZHVhdGVfZWxsW2dyYWR1YXRlX2VsbCA9PSAicyJdID0gTkEKZ3JhZHVhdGVfZWxsWyxjb2xzXSA8LSBhcHBseShncmFkdWF0ZV9lbGxbLGNvbHNdLCAyLCBmdW5jdGlvbih4KSBhcy5udW1lcmljKHgpKQpgYGAKCldlIGltcG9ydGVkIHRoZSBkYXRhc2V0IG9mIGdyYWR1YXRpb24gaW5kaWNhdG9ycyBieSBFbmdsaXNoIGxldmVsLCB1dGlsaXppbmcgdGhlIHRlY2huaXF1ZXMgd2UgdXNlZCBiZWZvcmUgaW5jbHVkaW5nIHN0YW5kYXJkaXppbmcgbWlzc2luZyBkYXRhIGFuZCB0cmFuc2ZlcnJpbmcgdGhlIGRhdGEgdHlwZSBvZiBmZWF0dXJlcy4KCmBgYHtyfQojI3JlbW92ZSB0aGUgbWlzc2luZyBkYXRhIGluIHBlcl9ncmFkc19jb2hvcnQKZ3JhZHVhdGVfZWxsIDwtIGdyYWR1YXRlX2VsbFtjb21wbGV0ZS5jYXNlcyhncmFkdWF0ZV9lbGwpLF0KZ3JhZHVhdGVfZWxsIDwtIGdyYWR1YXRlX2VsbCU+JSBmaWx0ZXIoRGlzdHJpY3QhPTc5KQoKYGBgCgpXZSBpbXBsZW1lbnRlZCB0aGUgc2ltaWxhciBkYXRhIHByZXByb2Nlc3Npbmcgc3RhdGVkIGFzIGFib3ZlIHRvIHByZXBhcmUgdGhlIGRhdGEgc2V0IGZvciBhbmFseXNpcy4gCldlIGZpZ3VyZWQgb3V0IHRoYXQgYSBmZXcgb2JzZXJ2YXRpb25zIGFyZSBtaXNzaW5nIG9uIGFsbCBpbmNsdWRlZCB2YXJpYWJsZXMuIFRoZXJlZm9yZSwgd2UgZGVjaWRlZCB0byByZW1vdmUgYWxsIHRoZSBtaXNzaW5nIG9ic2VydmF0aW9ucywgc2luY2UgdGhlIG51bWJlciBvZiBtaXNzaW5nIG9ic2VydmF0aW9ucyB3YXMgcmF0aGVyIHNtYWxsIGNvbXBhcmVkIHRvIHRoZSB0b3RhbCBkYXRhIHNldC4KCkJlc2lkZXMsIHdlIGZvdW5kIG91dCB0aGVyZSB3YXMgYW4gZXh0cmEgZGlzdHJpY3QgNzksIE5ldyBZb3JrIENpdHkncyBBbHRlcm5hdGl2ZSBTY2hvb2xzIERpc3RyaWN0LCBpbmNsdWRlZCBpbiB0aGUgZGF0YSBzZXQuIFNpbmNlIGl0IHdhcyBub3QgdGhlIGZvY3VzIG9mIG91ciByZXNlYXJjaCwgd2UgZGVjaWRlZCB0byBkcm9wIHRoZSBvYnNlcnZhdGlvbnMgb2YgRGlzdHJpY3QgNzkgdG8gYXZvaWQgdGhlIGluZmx1ZW5jZS4KCiMjIyMgKGkpIEdyYWR1YXRpb24gUmF0ZSBBbmFseXNpcyBieSBFbmdsaXNoIExldmVsIGFuZCBEaXN0cmljdApgYGB7cn0KZ3JhZHVhdGVfZWxsX3BoaXN0IDwtIGdyYWR1YXRlX2VsbCAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnksQ29ob3J0X1llYXIpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKHN1bV9wZXJfZ3JhZD0gc3VtKG51bV9ncmFkcykvc3VtKG51bV9jb2hvcnQpKQoKCmdyYWR1YXRlX2VsbF9wZXIgPC0gZ3JhZHVhdGVfZWxsICU+JSAKICBncm91cF9ieShDYXRlZ29yeSwgRGlzdHJpY3QpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKHN1bV9wZXJfZ3JhZD0gc3VtKG51bV9ncmFkcykvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX2Ryb3BvdXQ9IHN1bShudW1fZHJvcG91dCkvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3JlZ2VudD1zdW0obnVtX3JlZ2VudHMpIC9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfYWRyZWdlbnQ9IHN1bShudW1fYWRyZWdlbnRzKSAvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3dhZHJlZ2VudD0gc3VtKG51bV93YWRyZWdlbnRzKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfbG9jYWwgPSBzdW0obnVtX2xvY2FsKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfc2FjYz0gc3VtKG51bV9TQUNDKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfdGFzYz0gc3VtKG51bV9UQVNDKS9zdW0obnVtX2NvaG9ydCkpCgpwaGlzdDwtIGdncGxvdChncmFkdWF0ZV9lbGxfcGhpc3QsIGFlcyh4ID1mYWN0b3IoQ29ob3J0X1llYXIpICwgeSA9IHN1bV9wZXJfZ3JhZCwgZmlsbCA9Q2F0ZWdvcnkpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICBsYWJzKHRpdGxlID0gIkdyYWR1YXRpb24gUmF0ZSB3aXRoIHJlc3BlY3QgdG8gRW5nbGlzaCBMZXZlbCIsIHggPSAiWWVhciIsIHkgPSAiR3JhZHVhdGlvbiBSYXRlIikKI2dyaWQuYXJyYW5nZShtYXRoX2hpc3QsIG1hdGhfcGNwLCBucm93ID0gMikKIApwbGluZTwtICBnZ3Bsb3QoZ3JhZHVhdGVfZWxsX3BlciAsIGFlcyh4ID0gRGlzdHJpY3QsICB5ID0gc3VtX3Blcl9ncmFkLCBjb2wgPSBDYXRlZ29yeSkgKSsKICBnZW9tX2xpbmUoKSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEsIDMyLCAxKSkgKwogIHlsaW0oMCwxKSsKICBsYWJzKHRpdGxlID0gIkdyYWR1YXRpb24gUmF0ZSB3aXRoIEVuZ2xpc2ggTGV2ZWwgYW5kIERpc3RyaWN0IiwgeCA9ICJEaXN0cmljdCIsIHkgPSAiR3JhZHVhdGlvbiBSYXRlIikKCmdyaWQuYXJyYW5nZShwaGlzdCwgcGxpbmUsIG5yb3cgPSAyKQpgYGAKRnJvbSB0aGUgYmFyIGNoYXJ0LCBpdCBpbmRpY2F0ZXMgdGhlIGdyYWR1YXRpb24gcmF0ZSB3aXRoIHJlc3BlY3QgdG8gRW5nbGlzaCBsZXZlbHMgZHVyaW5nIHRoZSBwZXJpb2QgZnJvbSAyMDAxIHRvIDIwMTIuIEluIG9yZGVyIHRvIGFjaGlldmUgdGhpcyBncmFwaCwgd2Ugc3VtbWFyaXplZCB0aGUgZ3JhZHVhdGlvbiByYXRlIGdyb3VwZWQgYnkgY2F0ZWdvcnkgYW5kIGNvaG9ydCB5ZWFyLgpPdmVyIHRoZSB5ZWFycywgdGhlIGdyYWR1YXRpb24gcmF0ZSBmb3IgRm9ybWVyIEVMTCB3YXMgdGhlIGJlc3QsIHdoaWxlIHRoZSByYXRlIGZvciBFTEwgd2FzIHRoZSB3b3JzdC4gQmVzaWRlcywgdGhvdWdoIHRoZSByYXRlIGZvciBFbmdsaXNoIFByb2ZpY2llbnQgd2FzIGluIHRoZSBtaWRkbGUsIGl0IHdhcyBncmFkdWFsbHkgaW5jcmVhc2luZyBhbmQgYXBwcm9hY2hpbmcgdG8gdGhlIG9uZSBmb3IgRm9ybWVyIEVMTC4KCkZyb20gdGhlIGxpbmUgZ3JhcGgsIGl0IHNob3dzIHRoZSBvdmVyYWxsIGdyYWR1YXRpb24gcmF0ZSBvZiB0aHJlZSBFbmdsaXNoIGxldmVscyBhbW9uZyB0aGUgMzIgZGlzdHJpY3RzLiBJbiBvcmRlciB0byBhY2hpZXZlIHRoaXMgZ3JhcGgsIHdlIHN1bW1hcml6ZWQgdGhlIGRpZmZlcmVudCBncmFkdWF0aW9uIGluZGljYXRvcnMgZ3JvdXBlZCBieSBjYXRlZ29yeSBhbmQgZGlzdHJpY3QuClRoZSBncmFkdWF0aW9uIHJhdGUgcGF0dGVybiBvdmVyIHRoZSBkaXN0cmljdHMgd2FzIHNoYXJlZCBieSB0aGUgdGhyZWUgRW5nbGlzaCBsZXZlbHMgZ2VuZXJhbGx5LiBIb3dldmVyLCBpbiB0aGUgRGlzdHJpY3QgMywgdGhlIHJhdGUgZm9yIEVuZ2xpc2ggUHJvZmljaWVudCB3YXMgc2xpZ2h0bHkgYmV0dGVyIHRoYW4gdGhlIG9uZSBmb3IgdGhlIEZvcm1lciBFTEwuIEFtb25nIGFsbCB0aGVzZSBkaXN0cmljdHMsIHRoZSBncmFkdWF0aW9uIHJhdGVzIGZvciBEaXN0cmljdCAxMyB3ZXJlIHRoZSBiZXN0IGZvciBhbGwgdGhyZWUgRW5nbGlzaCBjYXRlZ29yaWVzLCB3aGlsZSB0aGUgZ3JhZHVhdGlvbiByYXRlcyBmb3IgRGlzdHJpY3QgOCwxNiBhbmQgMjMgd2VyZSB0aGUgd29yc3QgZm9yIEVMTCwgRW5nbGlzaCBQcm9maWNpZW50LCBhbmQgRm9ybWVyIEVMTC4KVGhlcmUgd2VyZSBhbHNvIHNvbWUgc3BlY2lhbCBjYXNlcyBhbW9uZyBkaXN0cmljdHMuIEZvciBpbnN0YW5jZSwgdGhlIGRpZmZlcmVuY2UgaW4gZ3JhZHVhdGlvbiByYXRlcyBiZXR3ZWVuIEVMTCBhbmQgRW5nbGlzaCBQcm9maWNpZW50IHdhcyB0aGUgbGFyZ2VzdCBpbiBEaXN0cmljdCA2LCBzaW5jZSB0aGUgcmF0ZSBvZiBFbmdsaXNoIFByb2ZpY2llbnQgd2FzIGNsb3NlIHRvIHRoYXQgb2YgRm9ybWVyIEVMTC4gSG93ZXZlciwgdGhlIGdyYWR1YXRpb24gcmF0ZXMgb2YgRUxMIGFuZCBFbmdsaXNoIFByb2ZpY2llbnQgd2FzIHByZXR0eSBjbG9zZSBpbiBEaXN0cmljdCAxOC4KCiMjIyMgKGlpKSBHcmFkdWF0aW9uIEluZGljYXRvcnMgYnkgRW5nbGlzaCBMZXZlbHMKYGBge3J9CmdyYWR1YXRlX2VsbF90aWR5IDwtIGdyYWR1YXRlX2VsbCAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKHN1bV9wZXJfZ3JhZD0gc3VtKG51bV9ncmFkcykvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX2Ryb3BvdXQ9IHN1bShudW1fZHJvcG91dCkvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3JlZ2VudD1zdW0obnVtX3JlZ2VudHMpIC9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfYWRyZWdlbnQ9IHN1bShudW1fYWRyZWdlbnRzKSAvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3dhZHJlZ2VudD0gc3VtKG51bV93YWRyZWdlbnRzKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfbG9jYWwgPSBzdW0obnVtX2xvY2FsKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfc2FjYz0gc3VtKG51bV9TQUNDKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfdGFzYz0gc3VtKG51bV9UQVNDKS9zdW0obnVtX2NvaG9ydCkpCgpncmFkdWF0ZV9lbGxfdGlkeTwtZ3JhZHVhdGVfZWxsX3RpZHklPiVnYXRoZXIoSW5kaWNhdG9yLCBQZXJjZW50YWdlLCAtQ2F0ZWdvcnksLXN1bV9wZXJfZ3JhZCkKZ3JhZHVhdGVfZWxsX3RpZHkkSW5kaWNhdG9yPC1mYWN0b3IoZ3JhZHVhdGVfZWxsX3RpZHkkSW5kaWNhdG9yLGxldmVscz1jKCdzdW1fcGVyX3JlZ2VudCcsJ3N1bV9wZXJfYWRyZWdlbnQnLCdzdW1fcGVyX3dhZHJlZ2VudCcsJ3N1bV9wZXJfZHJvcG91dCcsJ3N1bV9wZXJfbG9jYWwnLCdzdW1fcGVyX3NhY2MnLCdzdW1fcGVyX3Rhc2MnKSkKYGBgCgpUaGVyZSB3YXMgYW4gYW5vdGhlciBjaGFsbGVuZ2Ugd2UgZW5jb3VudGVyZWQgd2hpbGUgZGF0YSBhbmFseXNpcy4gV2UgdHJpZWQgdG8gZmFjZXQgd3JhcCB0aGUgaW5kaWNhdG9yIHNvIGFzIHRvIHNob3cgdGhlIGRpZmZlcmVudCBncmFkdWF0aW9uIHJhdGVzIHdpdGggcmVzcGVjdCB0byBFbmdsaXNoIGxldmVscyBhZnRlciBzdW1tYXJpemluZyB0aGUgZ3JhZHVhdGlvbiByYXRlcyBncm91cGVkIGJ5IGNhdGVnb3J5LiBIb3dldmVyLCB0aGUgc3VtbWFyaXplZCBncmFkdWF0aW9uIGluZGljYXRvcnMgd2VyZSBpbiB3aWRlIGZvcm1zLCB0aHVzIHdlIGhhZCB0byB0cmFuc2Zvcm0gdGhlbSBpbnRvIHRoZSBsb25nIGZvcm1hdCBieSB1c2luZyBnYXRoZXIgZnVuY3Rpb24uCgpgYGB7cixmaWcud2lkdGg9MTAsZmlnLmhlaWdodD0xMH0KdG9fc3RyaW5nPC1hc19sYWJlbGxlcihjKCdzdW1fcGVyX2FkcmVnZW50Jz0nQWR2YW5jZWQgUmVnZW50IFJhdGUnLCdzdW1fcGVyX2Ryb3BvdXQnPSdEcm9wb3V0IFJhdGUnLCdzdW1fcGVyX2xvY2FsJz0nTG9jYWwgUmF0ZScsJ3N1bV9wZXJfcmVnZW50Jz0nUmVnZW50IFJhdGUnLCdzdW1fcGVyX3NhY2MnPSdTQUNDIFJhdGUnLCdzdW1fcGVyX3Rhc2MnPSdUQVNDIFJhdGUnLCdzdW1fcGVyX3dhZHJlZ2VudCc9J1dpdGhvdXQgQWR2YW5jZWQgUmVnZW50IFJhdGUnKSkKCmdncGxvdChncmFkdWF0ZV9lbGxfdGlkeSwgYWVzKHggPSBDYXRlZ29yeSwgeSA9IFBlcmNlbnRhZ2UsIGZpbGw9ZmFjdG9yKCBDYXRlZ29yeSkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBmYWNldF93cmFwKH5mYWN0b3IoSW5kaWNhdG9yKSxsYWJlbGxlcj10b19zdHJpbmcpICsKICBsYWJzKHRpdGxlID0gIkdyYWR1YXRpb24gSW5kaWNhdG9ycyBieSBFbmdsaXNoIExldmVsIiwgeCA9ICJFbmdsaXNoIExldmVsIiwgeSA9ICJJbmRpY2F0b3IgUHJlY2VudGFnZSIsZmlsbD0iQ2F0ZWdvcnkiKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEwLGFuZ2xlPTIwKSkKIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKyAKIyBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQocmV2ZXJzZT1UUlVFKSkKCmBgYApGb3IgZHJvcG91dCByYXRlLCBFTEwgd2FzIGhpZ2hlc3QsIHdoaWxlIEZvcm1lciBFTEwgd2FzIGxvd2VzdC4gRm9yIHRoZSBpbmRpY2F0b3JzIFJlZ2VudCByYXRlIGFuZCBXaXRob3V0IEFkdmFuY2VkIFJlZ2VudCBSYXRlLCBGb3JtZXIgRUxMIHdhcyB0aGUgYmVzdCwgdGhlbiB3YXMgRW5nbGlzaCBQcm9maWNpZW50LCB3aGlsZSBFTEwgd2FzIHRoZSB3b3JzdC4gSG93ZXZlciwgZm9yIHRoZSBBZHZhbmNlZCBSZWdlbnQgcmF0ZSwgRW5nbGlzaCBQcm9maWNpZW50IHdhcyBzbGlnaHRseSBiZXR0ZXIgdGhhbiB0aGUgRm9ybWVyIEVMTC4gQmVzaWRlcywgdGhlcmUgd2VyZSBmZXdlciBpbmRpdmlkdWFscyBvZiBFbmdsaXNoIFByb2ZpY2llbnQgdHlwZSBnZXR0aW5nIExvY2FsIERpcGxvbWFzKGFsbG93ZWQgdG8gZ3JhZHVhdGUgd2l0aCBmZXdlciBleGFtIHNjb3JlcykKClRoZXJlZm9yZSwgd2UgY291bGQgY29uY2x1ZGUgdGhhdCBGb3JtZXIgRUxMIHBlcmZvcm1zIGJldHRlciBmb3IgdGhlIGdlbmVyYWwgZ3JhZHVhdGlvbiByYXRlcywgd2hpbGUgdGhlIEVuZ2xpc2ggUHJvZmljaWVudCBwZXJmb3JtcyBiZXR0ZXIgZm9yIHRoZSBhZHZhbmNlZCBsZXZlbHMsIHdoaWNoIG1lYW5zIG1vcmUgc3R1ZGVudHMgb2YgRW5nbGlzaCBQcm9maWNpZW50IGVhcm5lZCBoaWdoIGV4YW0gc2NvcmVzIGFtb25nIHRoZSBncmFkdWF0ZSBzdHVkZW50cy4gQW5kIHRoZSBzdHVkZW50cyBhcyBFbmdsaXNoIGxlYXJuZXJzIHJhbmtlZCBsYXN0IGluIHZhcmlvdXMgZGltZW5zaW9ucy4KCiMjIyBjKSBHcmFkdWF0aW9uIFJhdGUgQW5hbHlzaXMgYnkgR2VuZGVyCmBgYHtyfQpncmFkdWF0ZV9nZW48LXJlYWQuY3N2KCIyMDE2IEdyYWR1YXRpb25fUmF0ZXNfUHVibGljX0Rpc3RyaWN0X0dlbmRlci5jc3YiLHNraXA9OCxjb2wubmFtZXMgPWNvbF9uYW1lcykKY29sczwtY29sX25hbWVzWzY6MjddCmdyYWR1YXRlX2dlbltncmFkdWF0ZV9nZW4gPT0gInMiXSA9IE5BCmdyYWR1YXRlX2dlblssY29sc10gPC0gYXBwbHkoZ3JhZHVhdGVfZ2VuWyxjb2xzXSwgMiwgZnVuY3Rpb24oeCkgYXMubnVtZXJpYyh4KSkKYGBgCgpXZSBpbXBvcnRlZCB0aGUgZGF0YXNldCBvZiBncmFkdWF0aW9uIGluZGljYXRvcnMgYnkgZ2VuZGVyLCB1dGlsaXppbmcgdGhlIHRlY2huaXF1ZXMgd2UgdXNlZCBiZWZvcmUgaW5jbHVkaW5nIHN0YW5kYXJkaXppbmcgbWlzc2luZyBkYXRhIGFuZCB0cmFuc2ZlcnJpbmcgdGhlIGRhdGEgdHlwZSBvZiBmZWF0dXJlcy4KCmBgYHtyfQojI3JlbW92ZSB0aGUgbWlzc2luZyBkYXRhIGluIHBlcl9ncmFkc19jb2hvcnQKZ3JhZHVhdGVfZ2VuIDwtIGdyYWR1YXRlX2dlbltjb21wbGV0ZS5jYXNlcyhncmFkdWF0ZV9nZW4pLF0KZ3JhZHVhdGVfZ2VuIDwtIGdyYWR1YXRlX2dlbiU+JSBmaWx0ZXIoRGlzdHJpY3QhPTc5KQpgYGAKV2UgaW1wbGVtZW50ZWQgdGhlIHNpbWlsYXIgZGF0YSBwcmVwcm9jZXNzaW5nIHN0YXRlZCBhcyBhYm92ZSB0byBwcmVwYXJlIHRoZSBkYXRhIHNldCBmb3IgYW5hbHlzaXMuIApXZSBmb3VuZCBvdXQgdGhhdCBhIGZldyBvYnNlcnZhdGlvbnMgd2VyZSBtaXNzaW5nIG9uIGFsbCBpbmNsdWRlZCB2YXJpYWJsZXMuIFRoZXJlZm9yZSwgd2UgZGVjaWRlZCB0byByZW1vdmUgYWxsIHRoZSBtaXNzaW5nIG9ic2VydmF0aW9ucywgc2luY2UgdGhlIG51bWJlciBvZiBtaXNzaW5nIG9ic2VydmF0aW9ucyB3YXMgcmF0aGVyIHNtYWxsIGNvbXBhcmVkIHRvIHRoZSB0b3RhbCBkYXRhIHNldC4KCkJlc2lkZXMsIHdlIGZvdW5kIG91dCB0aGVyZSB3YXMgYW4gZXh0cmEgZGlzdHJpY3QgNzksIE5ldyBZb3JrIENpdHkncyBBbHRlcm5hdGl2ZSBTY2hvb2xzIERpc3RyaWN0LCBpbmNsdWRlZCBpbiB0aGUgZGF0YSBzZXQuIFNpbmNlIGl0IHdhcyBub3QgdGhlIGZvY3VzIG9mIG91ciByZXNlYXJjaCwgd2UgZGVjaWRlZCB0byBkcm9wIHRoZSBvYnNlcnZhdGlvbnMgb2YgRGlzdHJpY3QgNzkgdG8gYXZvaWQgdGhlIGluZmx1ZW5jZS4KCiMjIyMgKGkpIEdyYWR1YXRpb24gUmF0ZSBBbmFseXNpcyBieSBHZW5kZXIsRGlzdHJpY3QgYW5kIFllYXIKYGBge3J9CmdyYWR1YXRlX2dlbl9waGlzdCA8LSBncmFkdWF0ZV9nZW4gJT4lIAogIGdyb3VwX2J5KENhdGVnb3J5LENvaG9ydF9ZZWFyKSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShzdW1fcGVyX2dyYWQ9IHN1bShudW1fZ3JhZHMpL3N1bShudW1fY29ob3J0KSkKCgpncmFkdWF0ZV9nZW5fcGVyIDwtIGdyYWR1YXRlX2dlbiAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnksIERpc3RyaWN0KSAlPiUgCiAgZHBseXI6OnN1bW1hcmlzZShzdW1fcGVyX2dyYWQ9IHN1bShudW1fZ3JhZHMpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9kcm9wb3V0PSBzdW0obnVtX2Ryb3BvdXQpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9yZWdlbnQ9c3VtKG51bV9yZWdlbnRzKSAvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX2FkcmVnZW50PSBzdW0obnVtX2FkcmVnZW50cykgL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl93YWRyZWdlbnQ9IHN1bShudW1fd2FkcmVnZW50cykvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX2xvY2FsID0gc3VtKG51bV9sb2NhbCkvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3NhY2M9IHN1bShudW1fU0FDQykvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3Rhc2M9IHN1bShudW1fVEFTQykvc3VtKG51bV9jb2hvcnQpKQoKcGhpc3Q8LSBnZ3Bsb3QoZ3JhZHVhdGVfZ2VuX3BoaXN0LCBhZXMoeCA9ZmFjdG9yKENvaG9ydF9ZZWFyKSAsIHkgPSBzdW1fcGVyX2dyYWQsIGZpbGwgPUNhdGVnb3J5KSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogICAgbGFicyh0aXRsZSA9ICJHcmFkdWF0aW9uIFJhdGUgd2l0aCByZXNwZWN0IHRvIEdlbmRlciBvdmVyIHRoZSB5ZWFycyIsIHggPSAiWWVhciIsIHkgPSAiR3JhZHVhdGlvbiBSYXRlIikKI2dyaWQuYXJyYW5nZShtYXRoX2hpc3QsIG1hdGhfcGNwLCBucm93ID0gMikKIApwbGluZTwtICBnZ3Bsb3QoZ3JhZHVhdGVfZ2VuX3BlciAsIGFlcyh4ID0gRGlzdHJpY3QsICB5ID0gc3VtX3Blcl9ncmFkLCBjb2wgPSBDYXRlZ29yeSkgKSsKICBnZW9tX2xpbmUoKSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEsIDMyLCAxKSkgKwogIHlsaW0oMCwxKSsKICBsYWJzKHRpdGxlID0gIkdyYWR1YXRpb24gUmF0ZSB3aXRoIEdlbmRlciBhbmQgRGlzdHJpY3QiLCB4ID0gIkRpc3RyaWN0IiwgeSA9ICJHcmFkdWF0aW9uIFJhdGUiKQoKZ3JpZC5hcnJhbmdlKHBoaXN0LCBwbGluZSwgbnJvdyA9IDIpCgpgYGAKSW4gb3JkZXIgdG8gYWNoaWV2ZSB0aGlzIGJhciBjaGFydCwgd2Ugc3VtbWFyaXplZCB0aGUgZ3JhZHVhdGlvbiByYXRlIGdyb3VwZWQgYnkgZ2VuZGVyIGFuZCBjb2hvcnQgeWVhci4KRnJvbSB0aGUgYmFyIGNoYXJ0LCB3ZSBoYXZlIGtub3duIHRoYXQgb3ZlciB0aGUgeWVhcnMsIHRoZSBncmFkdWF0aW9uIHJhdGUgb2YgZmVtYWxlcyB3YXMgYmV0dGVyIHRoYW4gdGhlIG9uZSBvZiB0aGUgbWFsZXMuIFRoZSByYXRlcyBvZiBib3RoIG1hbGVzIGFuZCBmZW1hbGVzIHNob3dlZCBhbiB1cHdhcmQgdHJlbmQgZnJvbSAyMDAxIHRvIDIwMTIuCgpJbiBvcmRlciB0byBhY2hpZXZlIHRoZSBsaW5lIGdyYXBoLCB3ZSBzdW1tYXJpemVkIHRoZSBkaWZmZXJlbnQgZ3JhZHVhdGlvbiBpbmRpY2F0b3JzIGdyb3VwZWQgYnkgZ2VuZGVyIGFuZCBkaXN0cmljdC4KQWNjb3JkaW5nIHRvIHRoZSBsaW5lIGdyYXBoLCB0aGUgRGlzdHJpY3QgMTMsMTIgYW5kIDMyIGhhZCB0aGUgbGVhc3QgZGlzcGFyaXR5IG9mIGdyYWR1YXRpb24gcmF0ZXMgYmV0d2VlbiBtYWxlcyBhbmQgZmVtYWxlcywgd2hpY2ggbWVhbnMgdGhlIG1hbGUgYW5kIGZlbWFsZSBzdHVkZW50cyBwZXJmb3JtIHZlcnkgc2ltaWxhciBpbiB0aGVzZSB0aHJlZSBkaXN0cmljdHMuIAoKIyMjIyAoaWkpIEdyYWR1YXRpb24gSW5kaWNhdG9ycyBieSBHZW5kZXIKYGBge3J9CmdyYWR1YXRlX2dlbl90aWR5IDwtIGdyYWR1YXRlX2dlbiAlPiUgCiAgZ3JvdXBfYnkoQ2F0ZWdvcnkpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKHN1bV9wZXJfZ3JhZD0gc3VtKG51bV9ncmFkcykvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX2Ryb3BvdXQ9IHN1bShudW1fZHJvcG91dCkvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3JlZ2VudD1zdW0obnVtX3JlZ2VudHMpIC9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfYWRyZWdlbnQ9IHN1bShudW1fYWRyZWdlbnRzKSAvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3dhZHJlZ2VudD0gc3VtKG51bV93YWRyZWdlbnRzKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfbG9jYWwgPSBzdW0obnVtX2xvY2FsKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfc2FjYz0gc3VtKG51bV9TQUNDKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfdGFzYz0gc3VtKG51bV9UQVNDKS9zdW0obnVtX2NvaG9ydCkpCgpncmFkdWF0ZV9nZWJfdGlkeTwtZ3JhZHVhdGVfZ2VuX3RpZHklPiVnYXRoZXIoSW5kaWNhdG9yLCBQZXJjZW50YWdlLCAtQ2F0ZWdvcnksLXN1bV9wZXJfZ3JhZCkKZ3JhZHVhdGVfZ2ViX3RpZHkkSW5kaWNhdG9yPC1mYWN0b3IoZ3JhZHVhdGVfZ2ViX3RpZHkkSW5kaWNhdG9yLGxldmVscz1jKCdzdW1fcGVyX3JlZ2VudCcsJ3N1bV9wZXJfYWRyZWdlbnQnLCdzdW1fcGVyX3dhZHJlZ2VudCcsJ3N1bV9wZXJfZHJvcG91dCcsJ3N1bV9wZXJfbG9jYWwnLCdzdW1fcGVyX3NhY2MnLCdzdW1fcGVyX3Rhc2MnKSkKCmBgYAoKV2UgdHJpZWQgdG8gZmFjZXQgd3JhcCB0aGUgZ3JhZHVhdGlvbiBpbmRpY2F0b3Igc28gYXMgdG8gc2hvdyB0aGUgZGlmZmVyZW50IGdyYWR1YXRpb24gcmF0ZXMgd2l0aCByZXNwZWN0IHRvIGdlbmRlciBhZnRlciBzdW1tYXJpemluZyB0aGUgZ3JhZHVhdGlvbiByYXRlcyBncm91cGVkIGJ5IGNhdGVnb3J5LiBIb3dldmVyLCB0aGUgc3VtbWFyaXplZCBncmFkdWF0aW9uIGluZGljYXRvcnMgd2VyZSBpbiB3aWRlIGZvcm1zLCB0aHVzIHdlIGhhZCB0byB0cmFuc2Zvcm0gdGhlbSBpbnRvIHRoZSBsb25nIGZvcm1hdCBieSB1c2luZyBnYXRoZXIgZnVuY3Rpb24uCgpgYGB7cixmaWcud2lkdGg9MTAsZmlnLmhlaWdodD0xMH0KdG9fc3RyaW5nPC1hc19sYWJlbGxlcihjKCdzdW1fcGVyX2FkcmVnZW50Jz0nQWR2YW5jZWQgUmVnZW50IFJhdGUnLCdzdW1fcGVyX2Ryb3BvdXQnPSdEcm9wb3V0IFJhdGUnLCdzdW1fcGVyX2xvY2FsJz0nTG9jYWwgUmF0ZScsJ3N1bV9wZXJfcmVnZW50Jz0nUmVnZW50IFJhdGUnLCdzdW1fcGVyX3NhY2MnPSdTQUNDIFJhdGUnLCdzdW1fcGVyX3Rhc2MnPSdUQVNDIFJhdGUnLCdzdW1fcGVyX3dhZHJlZ2VudCc9J1dpdGhvdXQgQWR2YW5jZWQgUmVnZW50IFJhdGUnKSkKCgpnZ3Bsb3QoZ3JhZHVhdGVfZ2ViX3RpZHksIGFlcyh4ID0gQ2F0ZWdvcnksIHkgPSBQZXJjZW50YWdlLCBmaWxsPUNhdGVnb3J5KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZmFjZXRfd3JhcCh+ZmFjdG9yKEluZGljYXRvciksbGFiZWxsZXI9dG9fc3RyaW5nKSArCiAgbGFicyh0aXRsZSA9ICJWYXJpb3VzIEdyYWR1YXRpb24gSW5kaWNhdG9ycyBieSBHZW5kZXIiLCB4ID0gIkdlbmRlciIsIHkgPSAiSW5kaWNhdG9yIFNjb3JlIixjb2w9IkNhdGVnb3J5IikrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCxhbmdsZT0wKSkKIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKyAKIyBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQocmV2ZXJzZT1UUlVFKSkKCmBgYApGcm9tIHRoZSBncmFwaCBhYm92ZSwgd2Ugbm90aWNlZCB0aGF0IG5vIG1hdHRlciBmb3IgUmVnZW50IHJhdGVzLCBvciBBZHZhbmNlZCBSZWdlbnQgcmF0ZXMgb3IgV2l0aG91dCBBZHZhbmNlZCBSZWdlbnRzIHJhdGVzLCBmZW1hbGVzIGhhZCBhbiBlZGdlIG92ZXIgbWFsZXMuIEZvciB0aGUgZHJvcHB1dCByYXRlLCB0aGUgcmF0ZSBiZWxvbmdlZCB0byBmZW1hbGVzIHdhcyBsb3dlci4KTmV2ZXJ0aGVsZXNzLCBpbiB0ZXJtcyBvZiB0aGUgbG9jYWwgcmF0ZSwgdGhlIHJhdGUgb2YgZmVtYWxlcyB3YXMgc2xpZ2h0bHkgYmlnZ2VyIHRoYW4gdGhlIG9uZSBvZiB0aGUgbWFsZXMuCgpJbiBjb25jbHVzaW9uLCBmZW1hbGVzIHBlcmZvcm0gYmV0dGVyIHRoYW4gbWFsZXMgZm9yIG1vc3Qgb2YgdGhlIGdyYWR1YXRpb24gaW5kaWNhdG9ycywgaW4gZGlmZmVyZW50IGRpc3RyaWN0cyBkdXJpbmcgdGhlIHBlcmlvZCBmcm9tIDIwMDEgdG8gMjAxMi4KCiMjIyBkKUdyYWR1YXRpb24gUmF0ZSBBbmFseXNpcyBieSBFdGhpbmljaXR5CmBgYHtyfQpncmFkdWF0ZV9ldGg8LXJlYWQuY3N2KCIyMDE2IEdyYWR1YXRpb25fUmF0ZXNfUHVibGljX0Rpc3RyaWN0X0V0aG5pY2l0eS5jc3YiLHNraXA9OCxjb2wubmFtZXMgPWNvbF9uYW1lcykKY29sczwtY29sX25hbWVzWzY6MjddCmdyYWR1YXRlX2V0aFtncmFkdWF0ZV9ldGggPT0gInMiXSA9IE5BCmdyYWR1YXRlX2V0aFssY29sc10gPC0gYXBwbHkoZ3JhZHVhdGVfZXRoWyxjb2xzXSwgMiwgZnVuY3Rpb24oeCkgYXMubnVtZXJpYyh4KSkKYGBgCldlIGltcG9ydGVkIHRoZSBkYXRhc2V0IG9mIGdyYWR1YXRpb24gaW5kaWNhdG9ycyBieSBldGhuaWNpdHksIHV0aWxpemluZyB0aGUgdGVjaG5pcXVlcyB3ZSB1c2VkIGJlZm9yZSBpbmNsdWRpbmcgc3RhbmRhcmRpemluZyBtaXNzaW5nIGRhdGEgYW5kIHRyYW5zZmVycmluZyB0aGUgZGF0YSB0eXBlIG9mIGZlYXR1cmVzLgoKYGBge3J9CiMjcmVtb3ZlIHRoZSBtaXNzaW5nIGRhdGEgaW4gcGVyX2dyYWRzX2NvaG9ydApncmFkdWF0ZV9ldGg8LSBncmFkdWF0ZV9ldGhbY29tcGxldGUuY2FzZXMoZ3JhZHVhdGVfZXRoKSxdCmdyYWR1YXRlX2V0aCA8LSBncmFkdWF0ZV9ldGglPiUgZmlsdGVyKERpc3RyaWN0IT03OSkKYGBgCldlIGltcGxlbWVudGVkIHRoZSBzaW1pbGFyIGRhdGEgcHJlcHJvY2Vzc2luZyBzdGF0ZWQgYXMgYWJvdmUgdG8gcHJlcGFyZSB0aGUgZGF0YSBzZXQgZm9yIGFuYWx5c2lzLiAKV2UgZm91bmQgb3V0IHRoYXQgYSBmZXcgb2JzZXJ2YXRpb25zIGFyZSBtaXNzaW5nIG9uIGFsbCBpbmNsdWRlZCB2YXJpYWJsZXMuIFRoZXJlZm9yZSwgd2UgZGVjaWRlZCB0byByZW1vdmUgYWxsIHRoZSBtaXNzaW5nIG9ic2VydmF0aW9ucywgc2luY2UgdGhlIG51bWJlciBvZiBtaXNzaW5nIG9ic2VydmF0aW9ucyB3YXMgcmF0aGVyIHNtYWxsIGNvbXBhcmVkIHRvIHRoZSB0b3RhbCBkYXRhIHNldC4KCkJlc2lkZXMsIHdlIGZvdW5kIG91dCB0aGVyZSB3YXMgYW4gZXh0cmEgZGlzdHJpY3QgNzksIE5ldyBZb3JrIENpdHkncyBBbHRlcm5hdGl2ZSBTY2hvb2xzIERpc3RyaWN0LCBpbmNsdWRlZCBpbiB0aGUgZGF0YSBzZXQuIFNpbmNlIGl0IHdhcyBub3QgdGhlIGZvY3VzIG9mIG91ciByZXNlYXJjaCwgd2UgZGVjaWRlZCB0byBkcm9wIHRoZSBvYnNlcnZhdGlvbnMgb2YgRGlzdHJpY3QgNzkgdG8gYXZvaWQgdGhlIGluZmx1ZW5jZS4KCgojIyMjIChpKSBHcmFkdWF0aW9uIFJhdGUgQW5hbHlzaXMgYnkgRXRobmljaXR5LERpc3RyaWN0IGFuZCBZZWFyCmBgYHtyfQoKZ3JhZHVhdGVfZXRoX2hlYXQ8LSBncmFkdWF0ZV9ldGggJT4lCiAgICBncm91cF9ieShEaXN0cmljdCxDYXRlZ29yeSkgJT4lIAogICAjIGRwbHlyOjpzdW1tYXJpc2UobnVtX2dyYWRzPSBzdW0obnVtX2NvaG9ydCkpCiAgICAgZHBseXI6OnN1bW1hcmlzZShzdW1fcGVyX2dyYWQ9IHN1bShudW1fZ3JhZHMpL3N1bShudW1fY29ob3J0KSkKCmdyYWR1YXRlX2V0aF9oZWF0JERpc3RyaWN0IDwtIGZhY3RvcihncmFkdWF0ZV9ldGhfaGVhdCREaXN0cmljdCkgICAgIAoKZ2dwbG90KGdyYWR1YXRlX2V0aF9oZWF0LCBhZXMoQ2F0ZWdvcnksRGlzdHJpY3QsZmlsbCA9IHN1bV9wZXJfZ3JhZCkpICsgCiAgICBnZW9tX3RpbGUoKSArCiAgICMgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9cm91bmQoc3VtX3Blcl9ncmFkLDMpKSwgY29sb3IgPSAid2hpdGUiLHNpemU9MykgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9MCkpKwogICAgc2NhbGVfZmlsbF92aXJpZGlzKCkrCiAgICBsYWJzKHRpdGxlID0gIlRoZSBHcmFkdWF0aW9uIFJhdGUgb2YgRGlmZmVyZW50IEV0aG5pY2l0aWVzIGluIERpc3RyaWN0cyIsZmlsbD0iR3JhZHVhdGlvbiBSYXRlIikKCgpgYGAKQXQgZmlyc3QsIHdlIHRyaWVkIHRvIGRlbW9uc3RyYXRlIHRoZSBncmFkdWF0aW9uIHJhdGUgb2YgZGlmZmVyZW50IGV0aG5pY2l0aWVzIGluIGRpc3RyaWN0cyB1c2luZyBhIGxpbmUgZ3JhcGggb3IgaGlzdG9ncmFtLCBidXQgd2UgZmlndXJlZCBvdXQgdGhhdCB0aGUgbnVtYmVyIG9mIGNhdGVnb3JpZXMgd2FzIHRvbyBsYXJnZSB0byBleHBsaWNpdGx5IHNob3cgdGhlIGRpZmZlcmVuY2VzLiBUaGVyZWZvcmUsIHdlIGRlY2lkZWQgdG8gdXRpbGl6ZSBoZWF0bWFwIHRvIGluZGljYXRlIHRoZSBncmFkdWF0aW9uIHJhdGUgZGlmZmVyZW5jZXMgd2l0aCByZXNwZWN0IHRvIGRpc3RyaWN0cyBhbmQgZXRobmljaXRpZXMuCgpGcm9tIHRoZSBoZWF0bWFwIGFib3ZlLCB3ZSBmb3VuZCBvdXQgdGhhdCB0aGVyZSB3ZXJlIHNvbWUgbWlzc2luZyBkYXRhIGZvciBBc2lhbiBpbiBEaXN0cmljdCAxNiwgTXVsdGktUmFjaWFsIGFuZCBOYXRpdmUgQW1lcmljYW4gaW4gYSBmZXcgZGlzdHJpY3RzLiBJdCBkZW1vbnN0cmF0ZXMgdGhhdCBBc2lhbiBhbmQgTmF0aXZlIEFtZXJpY2FuIHBlcmZvcm1lZCB0aGUgYmVzdCBvdmVyIHRoZSBkaXN0cmljdHMsIHdoaWxlIE5hdGl2ZSBBbWVyaWNhbiBnb3QgdGhlIGxvd2VzdCBncmFkdWF0aW9uIHJhdGUgZXNwZWNpYWxseSBmb3IgRGlzdHJpY3QgMTYgYW5kIERpc3RyaWN0IDcuCgpGb3IgdGhlIEFzaWFuIGdyb3VwLCBkaXN0cmljdHMgMTMsIDEwLCA1IGFuZCA0IGdvdCB0aGUgYmVzdCBncmFkdWF0aW9uIHJhdGUsIHdoaWxlIGRpc3RyaWN0cyAyMyBhbmQgMTggZ290IHRoZSB3b3JzdCByYXRlLiAKCkluIHRlcm1zIG9mIHRoZSBNdWx0aS1SYWNpYWwgZ3JvdXAsIHRoZXkgZ290IHRoZSBiZXN0IHJhdGUgaW4gZGlzdHJpY3RzIDI5LCAyMSwgMTMsIDQgYW5kIDMsIHdoaWxlIHRoZXkgZ290IHRoZSB3b3JzdCBvbmUgaW4gRGlzdHJpY3QgMjcuCgpGb3IgdGhlIHdoaXRlIGdyb3VwLCB0aGUgZ3JhZHVhdGlvbiByYXRlIGRpZmZlcmVuY2Ugb3ZlciB0aGUgZGlzdHJpY3RzIHdhcyB0aGUgbW9zdCBvYnZpb3VzIGFtb25nIHRoZSBldGhuaWNpdHkgZ3JvdXBzLCB3aXRoIHRoZSBiZXN0IG9uZXMgaW4gRGlzdHJpY3QgMTMgYW5kIERpc3RyaWN0IDMsIGFuZCB0aGUgd29yc3Qgb25lcyBpbiBEaXN0cmljdCAyMyBhbmQgRGlzdHJpY3QgMTYuCgpgYGB7cn0KZ3JhZHVhdGVfZXRoX2xpbmU8LSBncmFkdWF0ZV9ldGggJT4lCiAgICBncm91cF9ieShDb2hvcnRfWWVhcixDYXRlZ29yeSkgJT4lIAogICAjIGRwbHlyOjpzdW1tYXJpc2UobnVtX2dyYWRzPSBzdW0obnVtX2NvaG9ydCkpCiAgICAgZHBseXI6OnN1bW1hcmlzZShzdW1fcGVyX2dyYWQ9IHN1bShudW1fZ3JhZHMpL3N1bShudW1fY29ob3J0KSkKCgpnZ3Bsb3QoZ3JhZHVhdGVfZXRoX2xpbmUgLCBhZXMoeCA9IENvaG9ydF9ZZWFyLCAgeSA9IHN1bV9wZXJfZ3JhZCwgY29sID0gQ2F0ZWdvcnkpICkrCiAgZ2VvbV9saW5lKHNpemU9MC44KSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDEsIDIwMTIsIDEpKSsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikrCiAgeWxpbSgwLDEpKwogIGxhYnModGl0bGUgPSAiR3JhZHVhdGlvbiBSYXRlIHdpdGggRXRobmljaXR5IG92ZXIgWWVhcnMiLCB4ID0gIlllYXIiLCB5ID0gIkdyYWR1YXRpb24gUmF0ZSIpCmBgYApGcm9tIHRoZSBsaW5lIGdyYXBoLCBpdCBpbmRpY2F0ZXMgdGhhdCBzdHVkZW50cyBjb3VsZCBiZSBkaXZpZGVkIGludG8gdHdvIGdyb3VwcyAtLSB0aGUgZmlyc3QgZ3JvdXAgd2l0aCByZWxhdGl2ZWx5IGhpZ2ggcmF0ZSBpbmNsdWRlcyBBc2lhbiwgV2hpdGUgYW5kIE11bHRpLVJhY2lhbCwgd2hpbGUgdGhlIHNlY29uZCBncm91cCB3aXRoIGxvd2VyIHJhdGUgY29udGFpbnMgQmxhY2ssIEhpc3BhbmljIGFuZCBOYXRpdmUgQW1lcmljYW4uCgpPdmVyIHRoZSB5ZWFycywgdGhlIGdyYWR1YXRpb24gcmF0ZXMgb2YgQXNpYW4sIFdoaXRlLCBCbGFjayBhbmQgSGlzcGFuaWMgd2VyZSBpbmNyZWFzaW5nIGdyYWR1YWxseS4gSG93ZXZlciwgZm9yIE11bHRpLVJhY2lhbCBhbmQgTmF0aXZlIEFtZXJpY2FuLCB0aGVyZSB3ZXJlIGEgZmV3IGZsdWN0dWF0aW9ucyBvdmVyIHRoZSB5ZWFycy4gRm9yIE11bHRpLVJhY2lhbCwgdGhlIHJhdGUgaGl0IHRoZSBsb3dlc3QgcG9pbnQgaW4gMjAwNCBhbmQgMjAwOSwgd2hpbGUgaXQgcmVhY2hlcyB0aGUgcGVhayBpbiAyMDA3IGFuZCAyMDEwLiBBcyBmb3IgTmF0aXZlIEFtZXJpY2FuLCAyMDA0IHdpdG5lc3NlZCB0aGUgY2xpbWF4IG9mIHRoZSBncmFkdWF0aW9uIHJhdGUuCgojIyMjIChpaSkgR3JhZHVhdGlvbiBJbmRpY2F0b3JzIGJ5IEV0aG5pY2l0eQpgYGB7cn0KZ3JhZHVhdGVfZXRoX3RpZHkgPC0gZ3JhZHVhdGVfZXRoICU+JSAKICBncm91cF9ieShDYXRlZ29yeSkgJT4lIAogIGRwbHlyOjpzdW1tYXJpc2Uoc3VtX3Blcl9ncmFkPSBzdW0obnVtX2dyYWRzKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfZHJvcG91dD0gc3VtKG51bV9kcm9wb3V0KS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfcmVnZW50PXN1bShudW1fcmVnZW50cykgL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9hZHJlZ2VudD0gc3VtKG51bV9hZHJlZ2VudHMpIC9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgIHN1bV9wZXJfd2FkcmVnZW50PSBzdW0obnVtX3dhZHJlZ2VudHMpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9sb2NhbCA9IHN1bShudW1fbG9jYWwpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9zYWNjPSBzdW0obnVtX1NBQ0MpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl90YXNjPSBzdW0obnVtX1RBU0MpL3N1bShudW1fY29ob3J0KSkKCmBgYAoKU2luY2UgdGhlIG51bWJlciBvZiBldGhuaWNpdHkgY2F0ZWdvcmllcyB3YXMgcmVsYXRpdmVseSBsYXJnZSwgd2UgYXBwbGllZCB0aGUgcGFyYWxsZWwgY29vcmRpbmF0ZSBpbnN0ZWFkIG9mIGhpc3RvZ3JhbSBhbmQgZmFjZXQgd3JhcCB0byBhbmFseXplIHRoZSBncmFkdWF0aW9uIGluZGljYXRvcnMgYnkgZXRobmljaXR5LgoKYGBge3J9CmdsYWJlbDwtYygnR3JhZHVhdGlvbiBSYXRlJywnRHJvcG91dCBSYXRlJywnUmVnZW50IFJhdGUnLCdBZHZhbmNlZCBSZWdlbnQgUmF0ZScsJ1dpdGhvdXQgQWR2YW5jZWQgUmVnZW50IFJhdGUnLCdMb2NhbCBSYXRlJywnU0FDQyBSYXRlJywnVEFTQyBSYXRlJykKZ2dwYXJjb29yZChncmFkdWF0ZV9ldGhfdGlkeSAsIGNvbHVtbnMgPTI6OSxzY2FsZT0iZ2xvYmFsbWlubWF4Iixncm91cENvbHVtbiA9ICJDYXRlZ29yeSIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTAsYW5nbGU9MTApKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz1nbGFiZWwpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSsKICBnZ3RpdGxlKCJHcmFkdWF0aW9uIEluZGljYXRvcnMgYnkgRXRobmljaXR5ICIpCgpgYGAKRm9yIEFzaWFuLCBNdWx0aS1SYWNpYWwgYW5kIFdoaXRlLCB0aGV5IGdvdCByZWxhdGl2ZWx5IGhpZ2ggZ3JhZHVhdGlvbiByYXRlIChvdmVyIDgwJSkgYW5kIGxvdyBkcm9wb3V0IHJhdGUoYWJvdXQgMTAlKS4gRm9yIHRoZSBjYXRlZ29yeSBBc2lhbiwgbWFqb3JpdHkgb2YgdGhlIGdyYWR1YXRlIHN0dWRlbnRzIGdvdCBSZWdlbnQgcmF0ZSwgd2hlcmUgdGhlIEFkdmFuY2VkIFJlZ2VudCByYXRlIHdhcyBoaWdoZXIgdGhhbiB0aGUgV2l0aG91dCBBZHZhbmNlZCBSZWdlbnQgcmF0ZS4gSW4gdGVybXMgb2YgTXVsdGktUmFjaWFsIGFuZCBXaGl0ZSBzdHVkZW50cywgdGhlIHN0dWRlbnRzIGdvdCBoaWdoZXIgV2l0aG91dCBBZHZhbmNlZCBSZWdlbnQgcmF0ZSBjb21wYXJlZCB0byBBZHZhbmNlZCBSZWdlbnQgcmF0ZS4KCkZvciB0aGUgb3RoZXIgdGhyZWUgZ3JvdXBzIEJsYWNrLCBIaXNwYW5pYyBhbmQgTmF0aXZlIEFtZXJpY2FuLCB0aGUgc3R1ZGVudHMgZWFybmVkIHJlbGF0aXZlbHkgbG93IGdyYWR1YXRpb24gcmF0ZSAoYWJvdXQgNjAlKSwgcmVsYXRpdmVseSBoaWdoIGRyb3BvdXQgcmF0ZSAoYWJvdXQgMjAlKSBhbmQgbG93IFJlZ2VudCByYXRlIChhYm91dCA1MCUpLCBtb3N0IG9mIHdoaWNoIHdlcmUgYmVsb25nZWQgdG8gV2l0aG91dCBBZHZhbmNlZCBSZWdlbnQgRGlwbG9tYS4gCgojIyMgZSkgR3JhZHVhdGlvbiBSYXRlIEFuYWx5c2lzIGJ5IFNXRApgYGB7cn0KZ3JhZHVhdGVfc3dkPC1yZWFkLmNzdigiMjAxNiBHcmFkdWF0aW9uX1JhdGVzX1B1YmxpY19EaXN0cmljdF9TV0QuY3N2Iixza2lwPTgsY29sLm5hbWVzID1jb2xfbmFtZXMpCmNvbHM8LWNvbF9uYW1lc1s2OjI3XQpncmFkdWF0ZV9zd2RbZ3JhZHVhdGVfc3dkID09ICJzIl0gPSBOQQpncmFkdWF0ZV9zd2RbLGNvbHNdIDwtIGFwcGx5KGdyYWR1YXRlX3N3ZFssY29sc10sIDIsIGZ1bmN0aW9uKHgpIGFzLm51bWVyaWMoeCkpCmBgYApXZSBpbXBvcnRlZCB0aGUgZGF0YXNldCBvZiBncmFkdWF0aW9uIGluZGljYXRvcnMgYnkgU1dELCB1dGlsaXppbmcgdGhlIHRlY2huaXF1ZXMgd2UgdXNlZCBiZWZvcmUgaW5jbHVkaW5nIHN0YW5kYXJkaXppbmcgbWlzc2luZyBkYXRhIGFuZCB0cmFuc2ZlcnJpbmcgdGhlIGRhdGEgdHlwZSBvZiBmZWF0dXJlcy4KCmBgYHtyfQojI3JlbW92ZSB0aGUgbWlzc2luZyBkYXRhIGluIHBlcl9ncmFkc19jb2hvcnQKZ3JhZHVhdGVfc3dkPC0gZ3JhZHVhdGVfc3dkW2NvbXBsZXRlLmNhc2VzKGdyYWR1YXRlX3N3ZCksXQpncmFkdWF0ZV9zd2QgPC0gZ3JhZHVhdGVfc3dkJT4lIGZpbHRlcihEaXN0cmljdCE9NzkpCmBgYApXZSBpbXBsZW1lbnRlZCB0aGUgc2ltaWxhciBkYXRhIHByZXByb2Nlc3Npbmcgc3RhdGVkIGFzIGFib3ZlIHRvIHByZXBhcmUgdGhlIGRhdGEgc2V0IGZvciBhbmFseXNpcy4gCldlIGZvdW5kIG91dCB0aGF0IGEgZmV3IG9ic2VydmF0aW9ucyBhcmUgbWlzc2luZyBvbiBhbGwgaW5jbHVkZWQgdmFyaWFibGVzLiBUaGVyZWZvcmUsIHdlIGRlY2lkZWQgdG8gcmVtb3ZlIGFsbCB0aGUgbWlzc2luZyBvYnNlcnZhdGlvbnMsIHNpbmNlIHRoZSBudW1iZXIgb2YgbWlzc2luZyBvYnNlcnZhdGlvbnMgd2FzIHJhdGhlciBzbWFsbCBjb21wYXJlZCB0byB0aGUgdG90YWwgZGF0YSBzZXQuCgpCZXNpZGVzLCB3ZSBmb3VuZCBvdXQgdGhlcmUgd2FzIGFuIGV4dHJhIGRpc3RyaWN0IDc5LCBOZXcgWW9yayBDaXR5J3MgQWx0ZXJuYXRpdmUgU2Nob29scyBEaXN0cmljdCwgaW5jbHVkZWQgaW4gdGhlIGRhdGEgc2V0LiBTaW5jZSBpdCB3YXMgbm90IHRoZSBmb2N1cyBvZiBvdXIgcmVzZWFyY2gsIHdlIGRlY2lkZWQgdG8gZHJvcCB0aGUgb2JzZXJ2YXRpb25zIG9mIERpc3RyaWN0IDc5IHRvIGF2b2lkIHRoZSBpbmZsdWVuY2UuCgpgYGB7cn0KCmdyYWR1YXRlX3N3ZF9oZWF0PC0gZ3JhZHVhdGVfc3dkICU+JQogICAgZ3JvdXBfYnkoRGlzdHJpY3QsQ2F0ZWdvcnkpICU+JSAKICAgIyBkcGx5cjo6c3VtbWFyaXNlKG51bV9ncmFkcz0gc3VtKG51bV9jb2hvcnQpKQogICAgIGRwbHlyOjpzdW1tYXJpc2Uoc3VtX3Blcl9ncmFkPSBzdW0obnVtX2dyYWRzKS9zdW0obnVtX2NvaG9ydCksCiAgICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3NhY2M9IHN1bShudW1fU0FDQykvc3VtKG51bV9jb2hvcnQpKQoKZ3JhZHVhdGVfc3dkX2hlYXQkRGlzdHJpY3QgPC0gZmFjdG9yKGdyYWR1YXRlX3N3ZF9oZWF0JERpc3RyaWN0KSAgICAgCgpwMTwtZ2dwbG90KGdyYWR1YXRlX3N3ZF9oZWF0LCBhZXMoQ2F0ZWdvcnksRGlzdHJpY3QsZmlsbCA9IHN1bV9wZXJfZ3JhZCkpICsgCiAgICBnZW9tX3RpbGUoKSArCiAgICMgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9cm91bmQoc3VtX3Blcl9ncmFkLDMpKSwgY29sb3IgPSAid2hpdGUiLHNpemU9MykgKwogICAjIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTEwKSkrCiAgICBzY2FsZV9maWxsX3ZpcmlkaXMoKSsKICAgIGxhYnModGl0bGUgPSAiVGhlIGdyYWR1YXRpb24gcmF0ZSBieSBzd2QgaW4gZGlzdHJpY3RzIixmaWxsPSJHcmFkdWF0aW9uIFJhdGUiKQoKcDI8LWdncGxvdChncmFkdWF0ZV9zd2RfaGVhdCwgYWVzKENhdGVnb3J5LERpc3RyaWN0LGZpbGwgPSBzdW1fcGVyX3NhY2MpKSArIAogICAgZ2VvbV90aWxlKCkgKwogICAjIGdlb21fdGV4dChhZXMobGFiZWwgPXJvdW5kKHN1bV9wZXJfc2FjYywzKSksIGNvbG9yID0gIndoaXRlIixzaXplPTMpICsKICAgIyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT0xMCkpKwogICAgc2NhbGVfZmlsbF92aXJpZGlzKCkrCiAgICBsYWJzKHRpdGxlID0gIlRoZSBTQUNDIHJhdGUgYnkgc3dkIGluIGRpc3RyaWN0cyIsZmlsbD0iU0FDQyBSYXRlIikKCmdyaWQuYXJyYW5nZShwMSxwMixucm93PTEpCmBgYApTV0QgbWVhbnMgU3R1ZGVudCB3aXRoIGEgRGlzYWJpbGl0eS4gU2luY2UgU0FDQyBDZXJ0aWZpY2F0ZSAoY2VydGlmaWNhdGUgZm9yIHN0dWRlbnRzIHdpdGggZGlzYWJpbGl0aWVzKSB3YXMgc3Ryb25nbHkgcmVsYXRlZCB0byB0aGUgZGlzYWJsZWQgc3R1ZGVudHMsIHdlIGRyZXcgdHdvIGhlYXRtYXBzIGZvciBjb21wYXJpc29uIC0tIG9uZSBpcyB0aGUgZ3JhZHVhdGlvbiByYXRlIGJ5IFNXRCBpbiBkaXN0cmljdHMsIGFuZCB0aGUgb3RoZXIgaXMgU0FDQyByYXRlIHdpdGggcmVzcGVjdCB0byBTV0QgaW4gZGlzdHJpY3RzLgoKRnJvbSB0aGUgaGVhdG1hcHMgYWJvdmUsIHdlIGF0dGVtcHRlZCB0byBzaG93IHRoZSBncmFkdWF0aW9uIHJhdGUgYW5kIFNBQ0MgcmF0ZSB3aXRoIHJlc3BlY3QgdG8gU1dELiBJbiB0ZXJtcyBvZiB0aGUgZ3JhZHVhdGlvbiByYXRlLCB0aGUgc3R1ZGVudHMgd2l0aG91dCBkaXNhYmlsaXR5IHBlcmZvcm0gYmV0dGVyIHRoYW4gdGhlIG9uZXMgd2l0aCBkaXNhYmlsaXR5IGFtb25nIHRoZSBkaXN0cmljdHMuIEFzIGZvciB0aGUgU0FDQyByYXRlLCBEaXN0cmljdCAxNiBoYWQgdGhlIGxhcmdlc3QgcGVyY2VudGFnZSBvZiBzdHVkZW50cyB3aXRoIGRpc2FiaWxpdHkgd2hvIGdvdCB0aGUgU0FDQyBDZXJ0aWZpY2F0ZSAoY2VydGlmaWNhdGUgZm9yIHN0dWRlbnRzIHdpdGggZGlzYWJpbGl0aWVzKS4KCiMjIyMgKGkpIEdyYWR1YXRpb24gSW5kaWNhdG9ycyBieSBTV0QKYGBge3J9CmdyYWR1YXRlX3N3ZF9saW5lPC0gZ3JhZHVhdGVfc3dkICU+JQogICAgZ3JvdXBfYnkoQ29ob3J0X1llYXIsQ2F0ZWdvcnkpICU+JSAKICAgIyBkcGx5cjo6c3VtbWFyaXNlKG51bV9ncmFkcz0gc3VtKG51bV9jb2hvcnQpKQogICAgZHBseXI6OnN1bW1hcmlzZShzdW1fcGVyX2dyYWQ9IHN1bShudW1fZ3JhZHMpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9kcm9wb3V0PSBzdW0obnVtX2Ryb3BvdXQpL3N1bShudW1fY29ob3J0KSwKICAgICAgICAgICAgICAgICAgICAgc3VtX3Blcl9yZWdlbnQ9c3VtKG51bV9yZWdlbnRzKSAvc3VtKG51bV9jb2hvcnQpLAogICAgICAgICAgICAgICAgICAgICBzdW1fcGVyX3NhY2M9IHN1bShudW1fU0FDQykvc3VtKG51bV9jb2hvcnQpKSU+JQogICAgIGdhdGhlcihJbmRpY2F0b3IsIFBlcmNlbnRhZ2UsIC1DYXRlZ29yeSwtQ29ob3J0X1llYXIpCgojZ3JhZHVhdGVfc3dkX2xpbmUkSW5kaWNhdG9yPC1mYWN0b3IoZ3JhZHVhdGVfc3dkX2xpbmUkSW5kaWNhdG9yLGxldmVscz1jKCdHcmFkdWF0aW9uIFJhdGUnLCdEcm9wb3V0IFJhdGUnLCdSZWdlbnQgUmF0ZScsJ1NBQ0MgUmF0ZScpKQoKZ2dwbG90KGdyYWR1YXRlX3N3ZF9saW5lICwgYWVzKHggPSBDb2hvcnRfWWVhciwgIHkgPSBQZXJjZW50YWdlLCBjb2wgPSBJbmRpY2F0b3IgKSApKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9Q2F0ZWdvcnkpLHNpemU9MC44KSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDEsIDIwMTIsIDEpKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIsbGFiZWxzPWMoJ0Ryb3BvdXQgUmF0ZScsJ0dyYWR1YXRpb24gUmF0ZScsJ1JlZ2VudCBSYXRlJywnU0FDQyBSYXRlJykpKwogIGxhYnModGl0bGUgPSAiR3JhZHVhdGlvbiBSYXRlIHdpdGggU1dEIGFuZCBEaXN0cmljdCIsIHggPSAiWWVhciIsIHkgPSAiR3JhZHVhdGlvbiBSYXRlIikKYGBgCldlIHdvdWxkIGxpa2UgdG8gc2hvdyB0aGUgdGltZSBzZXJpZXMgb2YgZGlmZmVyZW50IGdyYWR1YXRpb24gaW5kaWNhdG9ycyBpbiByZWdhcmQgdG8gU1dEIGNhdGVnb3J5IGluIGEgbGluZSBncmFwaCwgdGh1cyB3ZSBhcHBsaWVkIGdhdGhlciBmdW5jdGlvbiBhZnRlciBzdW1tYXJpemluZyB0aGUgdmFsdWVzIG9mIGluZGljYXRvcnMgYW5kIGVzdGFibGlzaGVkIHRoZSBsaW5lIGdyYXBoIHNldHRpbmcgY29sb3IgdG8gaW5kaWNhdG9yIGFuZCBsaW5lIHR5cGUgdG8gU1dEIGNhdGVnb3J5LgoKQWNjb3JkaW5nIHRvIGxpbmVzLCB0aGUgc3R1ZGVudHMgd2l0aG91dCBkaXNhYmlsaXR5IG91dHBlcmZvcm0gU1dEIGdlbmVyYWxseSBkdXJpbmcgdGhlIHllYXJzLgpPdmVyIHRoZSB5ZWFycywgdGhlIGdyYWR1YXRpb24gcmF0ZSBhbmQgcmVnZW50IHJhdGUgd2VyZSBnZXR0aW5nIGJldHRlciBpbiBib3RoIGdyb3VwcyBTV0QgYW5kIHN0dWRlbnRzIHdpdGhvdXQgZGlzYWJpbGl0eSwgZXNwZWNpYWxseSBmb3Igc3R1ZGVudHMgd2l0aG91dCBkaXNhYmlsaXR5LCB0aGUgcmVnZW50IHJhdGUgd2FzIGFwcHJvYWNoaW5nIHRvIGdyYWR1YXRpb24gcmF0ZS4KV2UgYWxzbyBub3RpY2VkIHRoYXQgdGhlIHJhdGUgb2YgU0FDQyBjZXJ0aWZpY2F0ZSB3YXMgZGVjcmVhc2luZyBmb3Igc3R1ZGVudHMgd2l0aCBkaXNhYmlsaXR5LgoKIyMjIGYpIFNBVCBBbmFseXNpcwpgYGB7cn0KU0FUPC1yZWFkLmNzdigiU0FUX1Jlc3VsdHMuY3N2IikKU0FUW1NBVD09InMiXTwtTkEKU0FUWywzOjZdIDwtIGFwcGx5KFNBVFssMzo2XSwgMiwgZnVuY3Rpb24oeCkgYXMubnVtZXJpYyh4KSkKU0FUIDwtIFNBVFtjb21wbGV0ZS5jYXNlcyhTQVQpLF0KCmBgYAoKV2UgaW1wb3J0ZWQgdGhlIGRhdGFzZXQgb2YgU0FUIHNjb3JlcywgdXRpbGl6aW5nIHRoZSB0ZWNobmlxdWVzIHdlIHVzZWQgYmVmb3JlIGluY2x1ZGluZyBzdGFuZGFyZGl6aW5nIG1pc3NpbmcgZGF0YSBhbmQgdHJhbnNmZXJyaW5nIHRoZSBkYXRhIHR5cGUgb2YgZmVhdHVyZXMuCgojIyMjIChpKSBTQVQgQXZlcmFnZSBTY29yZSBEaXN0cmlidXRpb24gb2YgZGlmZmVyZW50IHNjaG9vbHMKYGBge3J9CgpnMTwtZ2dwbG90KGRhdGE9bmEub21pdChTQVQpKSsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeD1hcy5udW1lcmljKGFzLmNoYXJhY3RlcihTQVQuQ3JpdGljYWwuUmVhZGluZy5BdmcuLlNjb3JlKSkpLGJpbndpZHRoID0gNSxmaWxsPSJwYXBheWF3aGlwIiwgY29sb3VyPSJraGFraTQiKSsKICB4bGFiKCJTQVQgQ3JpdGljYWwgUmVhZGluZyBBdmcuIFNjb3JlIikrCiAgZ2d0aXRsZSgiU0FUIEF2ZXJhZ2UgU2NvcmUgRGlzdHJpYnV0aW9uIG9mIGRpZmZlcmVudCBzY2hvb2xzIikKZzI8LWdncGxvdChkYXRhPW5hLm9taXQoU0FUKSkrCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoU0FULk1hdGguQXZnLi5TY29yZSkpKSxiaW53aWR0aCA9IDUsZmlsbD0icGFwYXlhd2hpcCIsIGNvbG91cj0ia2hha2k0IikrCiAgeGxhYigiU0FUIE1hdGggQXZnLiBTY29yZSIpCmczPC1nZ3Bsb3QoZGF0YT1uYS5vbWl0KFNBVCkpKwogIGdlb21faGlzdG9ncmFtKGFlcyh4PWFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFNBVC5Xcml0aW5nLkF2Zy4uU2NvcmUgKSkpLGJpbndpZHRoID0gNSxmaWxsPSJwYXBheWF3aGlwIiwgY29sb3VyPSJraGFraTQiKSsKICB4bGFiKCJTQVQgV3JpdGluZyBBdmcuIFNjb3JlIikKZ3JpZC5hcnJhbmdlKGcxLGcyLGczLG5yb3c9MykKCmBgYApUaGUgdGhyZWUgaGlzdG9ncmFtcyBzaG93IHRoZSBTQVQgYXZlcmFnZSBzY29yZSBvZiBkaWZmZXJlbnQgc2Nob29scywgd2hpY2ggYXJlIGFsbCByaWdodC1za2V3ZWQuIEluIHRoZSBwbG90IG9mIFNBVCBDcml0aWNhbCBSZWFkaW5nIEF2Zy4gU2NvcmUsIHRoZSBtYWpvcml0eSBvZiBhdmVyYWdlIHNjb3JlIGNlbnRlcmVkIGFyb3VuZCB0aGUgcmFuZ2UgWzM1MCw0MjBdLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlIGF2ZXJhZ2Ugc2NvcmUgb2YgbWF0aCBjb25jZW50cmF0ZWQgYXJvdW5kIDM3MCwgd2hpbGUgdGhlIHNjb3JlIG9mIHdyaXRpbmcgd2FzIGFyb3VuZCBbMzUwLDQwMF0uCgojIyMjIChpaSkgUHJvcG9ydGlvbiBvZiBTQVQgVGFrZXJzIG92ZXIgQ29ob3J0IFN0dWRlbnRzIGluIDMyIERpc3RyaWN0cwpgYGB7cn0KU0FUX3RpZHk8LVNBVCU+JW11dGF0ZShEaXN0cmljdD1zdWJzdHIoYXMuY2hhcmFjdGVyKERCTiksMSwyKSklPiVzZWxlY3QoRGlzdHJpY3QsTnVtLm9mLlNBVC5UZXN0LlRha2VycyxTQVQuQ3JpdGljYWwuUmVhZGluZy5BdmcuLlNjb3JlLFNBVC5NYXRoLkF2Zy4uU2NvcmUsU0FULldyaXRpbmcuQXZnLi5TY29yZSkKU0FUX3RpZHkkRGlzdHJpY3Q8LWFzLmZhY3RvcihTQVRfdGlkeSREaXN0cmljdCkKU0FUX3RpZHkgPC0gU0FUX3RpZHklPiUgZmlsdGVyKERpc3RyaWN0IT03OSAmIERpc3RyaWN0IT03NSklPiUKICBtdXRhdGUoc3VtX3JlYWRpbmcgPSBOdW0ub2YuU0FULlRlc3QuVGFrZXJzKlNBVC5Dcml0aWNhbC5SZWFkaW5nLkF2Zy4uU2NvcmUsIAogICAgICAgICBzdW1fbWF0aCA9IE51bS5vZi5TQVQuVGVzdC5UYWtlcnMqU0FULk1hdGguQXZnLi5TY29yZSwKICAgICAgICAgc3VtX3dyaXRpbmcgPSBOdW0ub2YuU0FULlRlc3QuVGFrZXJzKlNBVC5Xcml0aW5nLkF2Zy4uU2NvcmUgICklPiUKICBncm91cF9ieShEaXN0cmljdCklPiUgCiAgZHBseXI6OnN1bW1hcmlzZShyZWFkaW5nPXN1bShzdW1fcmVhZGluZykvc3VtKE51bS5vZi5TQVQuVGVzdC5UYWtlcnMpLAogICAgICAgICAgICAgICAgICAgbWF0aCA9IHN1bShzdW1fbWF0aCkvc3VtKE51bS5vZi5TQVQuVGVzdC5UYWtlcnMpLAogICAgICAgICAgICAgICAgICAgd3JpdGluZyA9IHN1bShzdW1fd3JpdGluZykvc3VtKE51bS5vZi5TQVQuVGVzdC5UYWtlcnMpLAogICAgICAgICAgICAgICAgICAgbnVtX3Rha2VyID1zdW0oTnVtLm9mLlNBVC5UZXN0LlRha2VycykpJT4lCiAgICAgICAgICAgICAgICAgICBnYXRoZXIoc2Vzc2lvbixzY29yZSwtRGlzdHJpY3QsLW51bV90YWtlcikKU0FUX3RpZHkkRGlzdHJpY3QgPC0gYXMubnVtZXJpYyhTQVRfdGlkeSREaXN0cmljdCApCmBgYAoKYGBge3J9CmdyYWR1YXRlX3M8LSBncmFkdWF0ZSU+JQogICAgZ3JvdXBfYnkoRGlzdHJpY3QpICU+JSAKICAgIyBkcGx5cjo6c3VtbWFyaXNlKG51bV9ncmFkcz0gc3VtKG51bV9jb2hvcnQpKQogICAgIGRwbHlyOjpzdW1tYXJpc2Uoc3VtX3Blcl9ncmFkPSBzdW0obnVtX2dyYWRzKS9zdW0obnVtX2NvaG9ydCksIAogICAgICAgICAgICAgICAgICAgICAgc3VtX2NvaG9ydCA9IHN1bShudW1fY29ob3J0KSkKZ3JhZF9TQVQ8LW1lcmdlKGdyYWR1YXRlX3MsU0FUX3RpZHksYnk9IkRpc3RyaWN0IikKCmBgYAoKSW4gb3JkZXIgdG8gY29ubmVjdCB0aGUgU0FUIHRha2VycyBvZiBkaWZmZXJlbnQgc2Nob29scyB3aXRoIHRoZSAzMiBkaXN0cmljdHMsIHdlIGV4dHJhY3RlZCB0aGUgRGlzdHJpY3QgcGFydCBmcm9tIHRoZSBEQk4gY29kZSBvZiBzY2hvb2xzLCBjcmVhdGluZyBuZXcgZmVhdHVyZXMgInJlYWRpbmciLCJtYXRoIiwid3JpdGluZyIgYW5kICJudW1fdGFrZXIiIHRvIGluZGljYXRlIHRoZSBhdmVyYWdlIHNjb3JlIG9mIHRha2VycyBpbiBkaXN0cmljdHMgYW5kIHRoZSBudW1iZXIgb2YgU0FUIHRha2VycyBpbiBkaXN0cmljdHMuClRoZW4gd2UgbWVyZ2VkIHRoZSBwcm9jZXNzZWQgU0FUIGRhdGFzZXQgd2l0aCB0aGUgZGF0YXNldCBvZiBncmFkdWF0aW9uIHJhdGVzIGFtb25nIGRpc3RyaWN0cy4gVGhlIHJlYXNvbiB3aHkgd2UgZ290IHRvIHRyYW5zZm9ybSB0aGUgZGF0YSB0eXBlIG9mIHRoZSAiRGlzdHJpY3QiIGZlYXR1cmUgdG8gbnVtZXJpYyBpbiBTQVRfdGlkeSB3YXMgYmVjYXVzZSB0aGUgZGF0YSB0eXBlIG9mIHRoZSAiRGlzdHJpY3QiIGZlYXR1cmUgaW4gZ3JhZHVhdGVfcyBkYXRhIGZyYW1lIHdhcyBudW1lcmljLiBJbiBvcmRlciB0byBtZXJnZSB0d28gZGF0YSBzZXRzLCB3ZSBoYWQgdG8gdW5pZnkgdGhlIGRhdGEgdHlwZSBvZiB0aGUgZmVhdHVyZS4KCkJlc2lkZXMsIHdlIGZvdW5kIG91dCB0aGVyZSB3ZXJlIGV4dHJhIGRpc3RyaWN0cyA3NSBhbmQgNzksIGluY2x1ZGVkIGluIHRoZSBkYXRhIHNldC4gU2luY2UgdGhlIHR3byBkaXN0cmljdHMgd2VyZSBub3QgdGhlIGZvY3VzIG9mIG91ciByZXNlYXJjaCwgd2UgZGVjaWRlZCB0byBkcm9wIHRoZSBvYnNlcnZhdGlvbnMgb2YgRGlzdHJpY3QgNzkgYW5kIERpc3RyaWN0IDc1IHRvIGF2b2lkIHRoZSBpbmZsdWVuY2UuCgoKYGBge3J9ClNBVF90YWtlcjwtZ3JhZF9TQVQgJT4lbXV0YXRlKHBlcl90YWtlciA9IG51bV90YWtlci9zdW1fY29ob3J0KSU+JXNlbGVjdChEaXN0cmljdCxwZXJfdGFrZXIpClNBVF90YWtlcjwtdW5pcXVlKFNBVF90YWtlcikKU0FUX3Rha2VyJERpc3RyaWN0PC1hcy5mYWN0b3IoU0FUX3Rha2VyJERpc3RyaWN0KQpnZ3Bsb3QoU0FUX3Rha2VyLCBhZXMoeCA9IERpc3RyaWN0LCB5ID0gcGVyX3Rha2VyKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLGZpbGw9InBhcGF5YXdoaXAiLCBjb2xvdXI9ImtoYWtpNCIpICsKICBsYWJzKHRpdGxlID0gIlBlcmNlbnRhZ2Ugb2YgU0FUIFRha2VycyBvdmVyIENvaG9ydCBTdHVkZW50cyBpbiAzMiBEaXN0cmljdHMiLCB4ID0gIkRpc3RyaWN0IiwgeSA9ICJQZXJjZW50YWdlIikrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMCxhbmdsZT0wKSkKCmBgYApXZSB1dGlsaXplZCBtdXRhdGUgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mIHN0dWRlbnRzIHRha2luZyBTQVQgaW4gMzIgZGlzdHJpY3RzLgoKVGhlIGJhciBjaGFydCBzaG93cyB0aGUgcHJvcG9ydGlvbiBvZiB0aGUgcmVjb3JkZWQgU0FUIHRha2VycyB3aXRoaW4gdGhlIGNvaG9ydCBzdHVkZW50cyBpbiAzMiBkaXN0cmljdHMuIEl0IGlzIHdvcnRoIG1lbnRpb25pbmcgdGhhdCB0aGUgcGVyY2VudGFnZSBvZiBTQVQgdGFrZXJzIHNob3duIGFib3ZlIGp1c3QgcmVmZXJzIHRvIHRoZSBvYnNlcnZhdGlvbnMgb2YgdGhlIGRhdGFzZXQsIGJ1dCBub3QgdGhlIHJlYWwgbnVtYmVyIG9mIGluZGl2aWR1YWxzIHRha2luZyBTQVQgZXhhbXMuCQoKIyMjIyAoaWlpKSBTQVQgU2NvcmVzIG9mIERpZmZlcmVudCBTZXNzaW9ucyB3aXRoIHJlc3BlY3QgdG8gRGlzdHJpY3QKYGBge3J9ClNBVF90aWR5JERpc3RyaWN0PC1hcy5udW1lcmljKFNBVF90aWR5JERpc3RyaWN0KQpTQVRfdGlkeSRzZXNzaW9uPC1hcy5mYWN0b3IoU0FUX3RpZHkkc2Vzc2lvbikKZ2dwbG90KFNBVF90aWR5KSsKICBnZW9tX2xpbmUoYWVzKHggPSBEaXN0cmljdCwgIHkgPSBzY29yZSwgY29sID0gc2Vzc2lvbikpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMSwgMzIsIDEpKSArCiAgeWxpbSgwLDU3MCkrCiAgbGFicyh0aXRsZSA9ICJTQVQgU2NvcmVzIG9mIERpZmZlcmVudCBzZXNzaW9ucyB3aXRoIERpc3RyaWN0IiwgeCA9ICJEaXN0cmljdCIsIHkgPSAiU2NvcmVzIikKCmBgYApBY2NvcmRpbmcgdG8gdGhlIGxpbmUgZ3JhcGgsIHdlIGZvdW5kIG91dCB0aGF0LCBhbW9uZyBhbGwgdGhlIGRpc3RyaWN0cywgdGhlIGF2ZXJhZ2UgbWF0aCBzY29yZXMgd2VyZSBoaWdoZXN0IHRoYW4gdGhlIHJlYWRpbmcgc2NvcmVzIGFuZCB0aGUgd3JpdGluZyBzY29yZXMuIEJlc2lkZXMsIHRoZSBhdmVyYWdlIHJlYWRpbmcgc2NvcmVzIHdlcmUgc2xpZ2h0bHkgaGlnaGVyIHRoYW4gdGhlIHdyaXRpbmcgc2NvcmVzLgpUaGUgZGlzdHJpY3Qgd2l0aCB0aGUgYmVzdCBTQVQgc2NvcmVzIHdhcyBEaXN0cmljdCAxMywgd2hpbGUgdGhlIGRpc3RyaWN0cyB3aXRoIHRoZSB3b3JzdCBTQVQgc2NvcmVzIHdlcmUgRGlzdHJpY3QgMTIgYW5kIERpc3RyaWN0IDMyLgpJbiB0ZXJtcyBvZiB0aGUgZGlzcGFyaXR5IGFtb25nIHRoZSBzY29yZXMgb2YgdGhyZWUgc2Vzc2lvbnMsIERpc3RyaWN0IDIwLCAyNiBhbmQgMSBnb3QgdGhlIG1vc3QgZXZpZGVudCBkaXNwYXJpdHkuCgoKIyMjIyAoaXYpIFRoZSBSZWxhdGlvbnNoaXAgYmV0d2VlbiBHcmFkdWF0aW9uIFJhdGUgYW5kIFNBVCBTY29yZXMKYGBge3J9CmdncGxvdChncmFkX1NBVCwgYWVzKHg9c3VtX3Blcl9ncmFkLCB5PXNjb3JlKSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvdXI9c2Vzc2lvbikpK2dlb21fc21vb3RoKGFlcyhjb2xvdXI9c2Vzc2lvbikpKwogIHlsaW0oMCw2NTApKwogIGxhYnModGl0bGUgPSAiVGhlIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIEdyYWR1YXRpb24gUmF0ZSBhbmQgU0FUIFNjb3JlcyIsIHggPSAiZ3JhZHVhdG9pbiByYXRlIiwgeSA9ICJTY29yZXMiKQpgYGAKQWNjb3JkaW5nIHRvIHRoZSBwbG90LCBpdCBkZXNjcmliZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gZ3JhZHVhdGlvbiByYXRlIGFuZCBTQVQgc2NvcmVzIHVzaW5nIGJvdGggc2NhdHRlciBwbG90cyBhbmQgc21vb3RoIGxpbmVzLgoKRnJvbSB0aGUgc2xvcGUgb2YgdGhlIGdyYXBoLCB3ZSBmb3VuZCBvdXQgdGhhdCB0aGUgU0FUIHNjb3JlcyB3ZXJlIHNsaWdodGx5IHBvc2l0aXZlbHkgY29ycmVsYXRlZCB3aXRoIGdyYWR1YXRpb24gcmF0ZXMsIHdoaWNoIG1lYW5zIHRoZSBoaWdoZXIgZ3JhZHVhdGlvbiByYXRlIGNvbWVzIGFsb25nIHdpdGggdGhlIGhpZ2hlciBTQVQgc2NvcmVzLCBlc3BlY2lhbGx5IGZvciBtYXRoIHNjb3Jlcy4KCiMjICg0KSBTY2hvb2wgQW5hbHlzaXMKCiMjIyBhKSBTY2hvb2wgUHJvZ3Jlc3MgRXZhbHVhdGlvbgpgYGB7cn0KIyBjbGVhbgpwcm9ncmVzcyA8LSByZWFkLmNzdigicHJvZ3Jlc3MuY3N2IiwgaGVhZGVyPVRSVUUsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnByb2dyZXNzW3Byb2dyZXNzID09ICJOb25lIl0gPSBOQQpwcm9ncmVzc1twcm9ncmVzcyA9PSAiUGVuZGluZyJdID0gTkEKcHJvZ3Jlc3MgPC0gbmEub21pdChwcm9ncmVzcykKcHJvZyA8LSBwcm9ncmVzc1tjKDEsNCw1LDYsNyw4KV0KY29sbmFtZXMocHJvZykgPC0gYygiREIiLCAiMTAtMTEiLCIwOS0xMCIsIjA4LTA5IiwiMDctMDgiLCIwNi0wNyIpCnByb2cgPC0gcHJvZyAlPiUgZ2F0aGVyKFllYXIsIFJhdGluZywgMjo2KQpwcm9nW3Byb2cgPT0gIkEiXSA9IDQKcHJvZ1twcm9nID09ICJCIl0gPSAzCnByb2dbcHJvZyA9PSAiQyJdID0gMgpwcm9nW3Byb2cgPT0gIkQiXSA9IDEKcHJvZ1twcm9nID09ICJGIl0gPSAwCnByb2ckUmF0aW5nIDwtIGFzLm51bWVyaWMocHJvZyRSYXRpbmcpCnByb2cxIDwtIHVuaXF1ZShwcm9nICU+JSBpbm5lcl9qb2luKGxvYykpCgojIHBsb3QKcHJvZ19EIDwtIGRwbHlyOjpzdW1tYXJpemUoZ3JvdXBfYnkocHJvZzEsWWVhcixEaXN0cmljdCksIG1lYW4oUmF0aW5nKSkKcHJvZ19EJERpc3RyaWN0IDwtIGZhY3Rvcihwcm9nX0QkRGlzdHJpY3QpCmNvbG5hbWVzKHByb2dfRClbM10gPC0gIlJhdGluZyIKZ2dwbG90KHByb2dfRCwgYWVzKHkgPSBZZWFyLHggPSBEaXN0cmljdCwgZmlsbD1SYXRpbmcpKSArIGdlb21fcmFzdGVyKCkgKyBsYWJzKHRpdGxlID0gIiBTY2hvb2wgUHJvZ3Jlc3MgUmF0aW5nIE1lYW4gYnkgRGlzdHJpY3QgIikgKyAKdGhlbWVfZ3JleSgxMikKYGBgClByb2dyZXNzIFJlcG9ydHMgZ3JhZGVkIGVhY2ggc2Nob29sIHdpdGggYW4gQSwgQiwgQywgRCwgb3IgRiBhbmQgd2VyZSBiYXNlZCBvbiBzdHVkZW50IHByb2dyZXNzICg2MCUpLCBzdHVkZW50IHBlcmZvcm1hbmNlICgyNSUpLCBhbmQgc2Nob29sIGVudmlyb25tZW50ICgxNSUpLiBTY29yZXMgd2VyZSBiYXNlZCBvbiBjb21wYXJpbmcgcmVzdWx0cyBmcm9tIG9uZSBzY2hvb2wgdG8gYSBwZWVyIGdyb3VwIG9mIHVwIHRvIDQwIHNjaG9vbHMgd2l0aCB0aGUgbW9zdCBzaW1pbGFyIHN0dWRlbnQgcG9wdWxhdGlvbiBhbmQgdG8gYWxsIHNjaG9vbHMgY2l0eXdpZGUuIFRoZXkgd2VyZSBkZXNpZ25lZCB0byBoZWxwIHBhcmVudHMsIHRlYWNoZXJzLCBwcmluY2lwYWxzLCBhbmQgb3RoZXJzIHVuZGVyc3RhbmQgaG93IHdlbGwgc2Nob29scyBhcmUgZG9pbmc/P2FuZCBjb21wYXJlIHRoZW0gdG8gb3RoZXIsIHNpbWlsYXIgc2Nob29scy4KCkZvciB0aGUgZGF0YXNldCBvZiBwcm9ncmVzcyByZXBvcnRzLCB3ZSBkZWxldGVkIG1pc3NpbmcgZGF0YSBhbmQgbWVhbmluZ2xlc3MgZGF0YSBhbmQgY2hhbmdlZCB0aGUgZ3JhZGUgQS1GIHRvIGludGVnZXIgNC0wIHRvIGhlbHAgdGhlIGRhdGEgdmlzdWFsaXphdGlvbi4gU2luY2UgdGhlIGRhdGFzZXQgcHJvdmlkZWQgdGhlIHByb2dyZXNzIGdyYWRlcyBvZiBhbGwgc2Nob29scyBpbiBOWUMsIHdlIGpvaW5lZCBpdCB3aXRoIHRoZSBkYXRhIG9mIGxvY2F0aW9uIGluZm9ybWF0aW9uIGFuZCBzdW1tcml6ZSB0aGVtIGJ5IGRpc3RyaWN0IHRvIGdldCB0aGUgYXZlcmFnZSByYXRpbmcgb2YgZWFjaCBkaXN0cmljdC4gd2UgdHJpZWQgdG8gdmlzdWFsaXplIGl0IHdpdGggcGFyYWxsZWwgY29vcmRpbmF0ZXMgYW5kIGhlYXRtYXAgYW5kIGZvdW5kIHRoYXQgaXQgd2FzIGVhc2llciBmb3IgdXMgdG8gZ2V0IGluZm9ybWF0aW9uIGFuZCBjb21wYXJlIHJhdGluZ3MgYmV0d2VlbiBkaWZmZXJlbnQgZGlzdHJpY3RzIGludHVpdGl2ZWx5IHdpdGggaGVhdG1hcC4KCkFjY29yZGluZyB0byB0aGUgZmlndXJlIGFib3ZlLCB3ZSBjYW4gZmluZCB0aGF0IHRoZSByYXRpbmcgb2YgYWxsIGRpc3RyaWN0cyBpbiAyMDA4LTIwMDkgYXJlIHJlbWFya2FibHkgaGlnaGVyIHRoYW4gdGhvc2UgaW4gb3RoZXIgeWVhcnMuIFRoaXMgaXMgd2VpcmQgYmVhY2F1c2UgdGhlIHJhdGluZyBhcmUgYmFzZWQgb24gY29tcGFyaW5nIHdpdGggc2ltaWxhciBzY2hvb2xzLiBUaGUgb3ZlcmFsbCByYXRpbmcgb2YgYWxsIGRpc3RyaWN0cyBzaG91bGQgbm90IGNoYW5nZSBhIGxvdCBvdmVyIHRoZSB5ZWFycy4gVGhlcmVmb3JlLCBXZSB0aGluayB0aGVyZSBpcyBzb21ldGhpbmcgd3Jvbmcgd2l0aCB0aGUgZGF0YSBvZiAyMDA4LTIwMDkuCldpdGhvdXQgY29uc2lkZXJpbmcgdGhlIGRhdGEgb2YgMjAwOC0yMDA5LCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBwcm9ncmVzcyByYXRpbmdzIG9mIGRpc3RyaWN0IDIsMjAsMjYgd2VyZSByZW1hcmthYmx5IGJldHRlciB0aGFuIG90aGVyIHRoYXQgb2YgdGhvc2Ugb2Ygb3RoZXIgZGlzdHJpY3RzIG92ZXIgdGhlIHllYXIsIHdoaWNoIG1lYW5zIHNjaG9vbHMgaW4gdGhlc2UgZGlzdHJpY3RzIGRvIGJldHRlciB0aGFuIHNjaG9vbHMgaW4gb3RoZXIgZGlzdHJpY3RzLgoKIyMjIGIpIFNjaG9vbCBRdWFsaXR5IEV2YWx1YXRpb24KYGBge3J9CiMgY2xlYW4KcXVhbGl0eSA8LSByZWFkLmNzdigiUXVhbGl0eVJldmlldy5jc3YiLCBoZWFkZXI9VFJVRSwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKY29sbmFtZXMocXVhbGl0eSkgPC0gYygiREJOIiwgIlllYXIiLCAiUmF0aW5nIikKcXVhbGl0eSA8LSBzZXBhcmF0ZShxdWFsaXR5LCBZZWFyLCBjKCJ4IiwgIlllYXIiKSwgc2VwPSJZIikKcXVhbGl0eSA8LSBxdWFsaXR5Wy0yXQpxdWFsaXR5W3F1YWxpdHkgPT0gIlUiXSA9IDAKcXVhbGl0eVtxdWFsaXR5ID09ICJVRCJdID0gMApxdWFsaXR5W3F1YWxpdHkgPT0gIlVQRiJdID0gMQpxdWFsaXR5W3F1YWxpdHkgPT0gIkQiXSA9IDIKcXVhbGl0eVtxdWFsaXR5ID09ICJQIl0gPSAzCnF1YWxpdHlbcXVhbGl0eSA9PSAiV0QiXSA9IDQKcXVhbGl0eVtxdWFsaXR5ID09ICJPIl0gPSA1CnF1YWxpdHkgPC0gcXVhbGl0eVstYygyOTk0LDM4MTIpLF0KcXVhbGl0eSA8LSB0cmFuc2Zvcm0ocXVhbGl0eSwgUmF0aW5nID0gYXMubnVtZXJpYyhSYXRpbmcpKQpxdWFsaXR5W3F1YWxpdHkgPT0gIiAxMS0xMiJdID0gIjExLTEyIgoKIyBwbG90CnF1YWxpdHlEYXRhMiA8LSB1bmlxdWUocXVhbGl0eSAlPiUgaW5uZXJfam9pbihsb2MpKQpxdWFsaXR5X0QgPC0gZHBseXI6OnN1bW1hcml6ZShncm91cF9ieShxdWFsaXR5RGF0YTIsWWVhcixEaXN0cmljdCksIG1lYW4oUmF0aW5nKSkKY29sbmFtZXMocXVhbGl0eV9EKVszXSA8LSAiUmF0aW5nIgpxdWFsaXR5X0QgPC0gc3Vic2V0KHF1YWxpdHlfRCwgICEgRGlzdHJpY3QgJWluJSBjKCIwIiwiNzUiKSApCnF1YWxpdHlfRCREaXN0cmljdCA8LSBmYWN0b3IocXVhbGl0eV9EJERpc3RyaWN0KQpnZ3Bsb3QocXVhbGl0eV9ELCBhZXMoeSA9IFllYXIseCA9IERpc3RyaWN0LCBmaWxsPVJhdGluZykpICsgZ2VvbV9yYXN0ZXIoKSArIGxhYnModGl0bGUgPSAiIFNjaG9vbCBRdWFsaXR5IFJhdGluZyBNZWFuIGJ5IERpc3RyaWN0ICIpICsgCnRoZW1lX2dyZXkoMTYpCmBgYApUaGUgUXVhbGl0eSBSZXZpZXcgaXMgYSBwcm9jZXNzIHRoYXQgZXZhbHVhdGVzIGhvdyB3ZWxsIHNjaG9vbHMgYXJlIG9yZ2FuaXplZCB0byBzdXBwb3J0IHN0dWRlbnQgbGVhcm5pbmcgYW5kIHRlYWNoZXIgcHJhY3RpY2UuIEl0IHdhcyBkZXZlbG9wZWQgdG8gYXNzaXN0IE5ldyBZb3JrIENpdHkgRGVwYXJ0bWVudCBvZiBFZHVjYXRpb24gKE5ZQ0RPRSkgc2Nob29scyBpbiByYWlzaW5nIHN0dWRlbnQgYWNoaWV2ZW1lbnQgYnkgbG9va2luZyBiZWhpbmQgYSBzY2hvb2w/P3MgcGVyZm9ybWFuY2Ugc3RhdGlzdGljcyB0byBlbnN1cmUgdGhhdCB0aGUgc2Nob29sIGlzIGVuZ2FnZWQgaW4gZWZmZWN0aXZlIG1ldGhvZHMgb2YgYWNjZWxlcmF0aW5nIHN0dWRlbnQgbGVhcm5pbmcuCgpGb3IgdGhlIHF1YWxpdHkgcmV2aWV3IGRhdGFzZXQsIHdlIHJlbW92ZWQgdGhlIHJlZHVwbGljYXRlZCBkYXRhIGFuZCBjaGFuZ2VkIHRoZSByZXN1bHRzLCBPLCBXRCwgUCwgZXRjLiB0byBpbnRlZ2VyLCBmcm9tIDAgdG8gNCBtYWtlIGl0IGVhc2llciBmb3IgdXMgdG8gdmlzdWFsaXplIHRoZSBkYXRhIHNldC4gU2luY2UgdGhlIGRhdGFzZXQgcHJvdmlkZWQgdGhlIHF1YWxpdHkgZ3JhZGVzIG9mIGFsbCBzY2hvb2xzIGluIE5ZQywgd2Ugam9pbmVkIGl0IHdpdGggdGhlIGRhdGEgb2YgbG9jYXRpb24gaW5mb3JtYXRpb24gYW5kIHN1bW1yaXplIHRoZW0gYnkgZGlzdHJpY3QgdG8gZ2V0IHRoZSBhdmVyYWdlIHJhdGluZyBvZiBlYWNoIGRpc3RyaWN0LiBDb21wYXJlZCB3aXRoIHBhcmFsbGVsIGNvb3JkaW5hdGVzIGFuZCBoaXN0b2dyYW0sIGhlYXRtYXAgY291bGQgc2hvdyB0aGUgY2hhbmdlIG9mIHF1YWxpdHkgcmF0aW5ncyBvdmVyIHllYXJzIGV4cGxpY2l0bHkgYW5kIGlzIGNvbnZlbmllbnQgZm9yIHVzIHRvIGNvbXBhcmUgdGhlIHF1YWxpdHkgcmF0aW5ncyBiZXR3ZWVuIGRpZmZlcmVudCBkaXN0cmljdHMuCgpGcm9tIHRoZSBmaWd1cmUsIHdlIGNhbiBmaW5kIHRoYXQgdGhlIG92ZXJhbGwgcmF0aW5nIG9mIGFsbCBkaXN0cmljdHMgd2VyZSBkZWNyZWFzaW5nIG92ZXIgdGhlc2UgeWVhcnMuIFRoaXMgY291bGQgYmUgcmVzdWx0ZWQgZnJvbSB0aGF0IGFsb25nIHdpdGggdGhlIGRldmVsb3BtZW50IG9mIHNvY2lldHksIHBlb3BsZSdzIHJlcXVpcmVtZW50IGxldmVsIGFyZSBpbmNyZWFzaW5nLgpCZXNpZGVzLCB3ZSBjYW4gZmluZCB0aGF0IHRoZSBxdWFsaXR5IHJhdGluZ3Mgb2YgZGlzdHJpY3QgMiwyMCwyNiB3ZXJlIHJlbWFya2FibHkgYmV0dGVyIHRoYW4gb3RoZXIgdGhhdCBvZiB0aG9zZSBvZiBvdGhlciBkaXN0cmljdHMgb3ZlciB0aGUgeWVhciwgd2hpY2ggbWVhbnMgc2Nob29scyBpbiB0aGVzZSBkaXN0cmljdHMgYXJlIGVuZ2FnZWQgaW4gbW9yZSBlZmZlY3RpdmUgbWV0aG9kcyBvZiBhY2NlbGVyYXRpbmcgc3R1ZGVudCBsZWFybmluZy4gQ29tYmluaW5nIHRoZSBpbmZvcm1hdGlvbiBmcm9tIHRoaXMgZmlndXJlIHdpdGggdGhhdCBmcm9tIHRoZSBhYm92ZSBmaWd1cmUsIHdlIGNhbiBjb25jbHVkZSB0aGF0IHNjaG9vbHMgaW4gZGlzdHJpY3QgMiwyMCwyNiBhcmUgZ29vZCBjaG9pY2UgZm9yIHBhcmVudHMgYW5kIGNoaWxkcmVuLgoKIyMgKDUpIEZ1cnRoZXIgQW5hbHlzaXMgd2l0aCBzb2NpYWwgbWF0dGVycwoKIyMjIGEpRXRobmljaXR5IEFuYWx5c2lzIGFuZCBQb2xpY3kKCkZyb20gdGhlIGFuYWx5c2lzIG9mIG1hdGggc2NvcmUsIEVMQSBzY29yZSwgZ3JhZHVhdGlvbiByYXRlIGFuZCBTQVQgc2NvcmUsIHdlIGZvdW5kIG91dCB0aGF0IEFzaWFuIGdvdCB0aGUgYmVzdCBwZXJmb3JtYW5jZSB3aGlsZSB0aGUgcGVyZm9ybWFuY2VzIG9mIEhpc3BhbmljLCBCbGFjayBhbmQgbmF0aXZlIEFtZXJpY2FuIHdlcmUgbm90IHRoYXQgZ29vZCwgZXNwZWNpYWxseSBmb3IgbmF0aXZlIEFtZXJpY2FuLgoKQWNjb3JkaW5nIHRvIHRoZSByZXBvcnQgUmFjZSwgRXRobmljaXR5LCBhbmQgRWR1Y2F0aW9uIFBvbGljeSwgKGh0dHBzOi8vc2Nob2xhci5oYXJ2YXJkLmVkdS9qbGhvY2hzY2hpbGQvcHVibGljYXRpb25zL3JhY2UtZXRobmljaXR5LWFuZC1lZHVjYXRpb24tcG9saWN5ICkgdGhlc2Ugb3V0Y29tZXMgcmVzdWx0IGZyb20gYSBjb21wbGV4IGludGVyYWN0aW9uIG9mIHJlc2lkZW50aWFsIGxvY2F0aW9uLCBmYW1pbHkgc29jaW9lY29ub21pYyBzdGF0dXMsIHBlcnNvbmFsIHByZWZlcmVuY2UsIGRpc2NyaW1pbmF0aW9uIG9yIGJpYXNlZCB0cmVhdG1lbnQsIGFuZCBxdWFsaXR5IG9mIHNjaG9vbGluZyBpbiB0aGUgMzIgZGlzdHJpY3RzICh0aGUgbWFqb3IgdG9waWMgd2UgcmVzZWFyY2ggb24pLiBFZHVjYXRpb25hbCBhdHRhaW5tZW50IGFuZCByYWNlIGFyZSBjbGVhcmx5IHJlbGF0ZWQsIGJ1dCBub3QgaW4gYW55IHNpbXBsZSBjYXVzYWwgd2F5LgoKT3V0IG9mIG1hbnkgcHJvcG9zYWxzIHRvIHRhY2tsZSB0aGUgcHJvYmxlbSBvZiBlZHVjYXRpb24gZGlzcGFyaXR5IGFtb25nIGV0aG5pY2l0eSBncm91cHMsIHNjaG9vbCBjaG9pY2UgaXMgdGhlIG9uZSBtZW50aW9uZWQgYW5kIGRlYmF0ZWQgdGhlIG1vc3Qg4oCTIHdoZXRoZXIgdG8gY2hvb3NlIGNoYXJ0ZXIgc2Nob29scyBvciBwcml2YXRpemVkIHZvdWNoZXIgcHJvZ3JhbXMuIEluIGZhY3QsIGZyb20gdGhlIGVtcGlyaWNhbCByZXNlYXJjaCBieSBNb2UgMjAwMSwgdm91Y2hlciBwcm9ncmFtcyBoYXZlIGZldyBpbXBsaWNhdGlvbiBvbiByYWlzaW5nIHRoZSBzdHVkZW50c+KAmSBhY2hpZXZlbWVudHMuIE9uIHRoZSBvdGhlciBoYW5kLCBjaGFydGVyIHNjaG9vbHMgYXJlIG1vcmUgc2lnbmlmaWNhbnQsIHNpbmNlIG92ZXIgYSBtaWxsaW9uIHN0dWRlbnRzIG5vdyBhdHRlbmQgdGhlbSAob3V0IG9mIDQ5IG1pbGxpb24gc3R1ZGVudHMgaW4gSy0xMiBzY2hvb2xzKS4gIFRoZSBudW1iZXIgb2YgY2hhcnRlciBzY2hvb2xzIGlzIGdyb3dpbmcsIGFuZCB0aGVpciBzdHJ1Y3R1cmUgYW5kIG9yZ2FuaXphdGlvbiBzZWVtIHRvIGJlIHN0YWJpbGl6aW5nLiBTb21lIGFyZSBsYXVkZWQgYXMgdGhlIGJlc3QgaG9wZSBmb3IgcG9vciBCbGFjayBhbmQgSGlzcGFuaWMgY2hpbGRyZW4sIGJ1dCBvdGhlcnMgd29ycnkgdGhhdCBjaGFydGVyIHNjaG9vbHMgb3Blbmx5LCBvciBpbXBsaWNpdGx5IHJlaW5mb3JjZSByYWNpYWwgc3RyYXRpZmljYXRpb24uCgpUaGVyZSBhcmUgYWxzbyBzb21lIHBvbGljaWVzIHNldCB1cCB0byBkZWNyZWFzZSB0aGUgZWR1Y2F0aW9uIGdhcCBvdmVyIHRoZSBldGhuaWNpdGllcy4KSW4gb3JkZXIgdG8gbWFrZSBzdXJlIGNoaWxkcmVuIG9mIGRpZmZlcmVudCBncm91cHMgdG8gcmVhY2ggdGhlIHNpbWlsYXIgYWNhZGVtaWMgbGV2ZWwsIE5ZQyBkZXBhcnRtZW50IG9mIGVkdWNhdGlvbihET0UpIGFsc28gaW1wbGVtZW50ZWQgYSBwb2xpY3kgY2FsbGVkIE5vIENoaWxkIExlZnQgQmVoaW5kLAooaHR0cDovL3NjaG9vbHMubnljLmdvdi9SdWxlc1BvbGljaWVzL05DTEIvZGVmYXVsdC5odG0gKSB3aGVyZSB0aGUgRE9FIHdpbGwgcHJvdmlkZSBzY2hvb2xzIGlkZW50aWZpZWQgYnkgdGhlIHN0YXRlIGFzIFByaW9yaXR5IGFuZCBGb2N1cyBTY2hvb2xzIHdpdGggZnVuZGluZyBzbyB0aGV5IG1heSBvZmZlciBvdGhlciB0eXBlcyBvZiBFeHBhbmRlZCBMZWFybmluZyBUaW1lIChFTFQpIHByb2dyYW1zIHRocm91Z2ggdGhlIE1UQUMgcHJvY2Vzcy4gVGhlIGVkdWNhdGlvbiBkZXNpZ24gcmVzdWx0cyBmcm9tIHRoZSBmZWRlcmFsIE5DTELigJlzIGVtcGhhc2lzIG9uIHNjaG9vbHPigJkg4oCcYWRlcXVhdGUgeWVhcmx5IHByb2dyZXNzLOKAnSBkZXRlcm1pbmVkIGJ5IHN0YW5kYXJkaXplZCB0ZXN0cyBkZXZpc2VkIGJ5IGVhY2ggc3RhdGUuIE5DTEIgcmVxdWlyZXMgdGhhdCwgd2l0aCBhIGZldyBleGNlcHRpb25zLCBzY2hvb2xzIGJyZWFrIG91dCB0aGVpciBwZXJmb3JtYW5jZSBieSByYWNpYWwgb3IgZXRobmljIHN1Ymdyb3VwLCBhbmQgc2hvdyBhZGVxdWF0ZSB5ZWFybHkgcHJvZ3Jlc3MgZm9yIGVhY2ggZ3JvdXAuCgojIyMgYikgR2VuZGVyIEFuYWx5c2lzIGFuZCBQb2xpY3kKCkZyb20gdGhlIHBsb3RzIHdlIGRyZXcsIHdlIGZpZ3VyZWQgb3V0IHRoYXQsIGluIGdlbmVyYWwsIGZlbWFsZXMgc2xpZ2h0bHkgb3V0cGVyZm9ybWVkIG1hbGVzIG5vIG1hdHRlciBmb3IgdGhlIG1hdGggc2NvcmVzIG9yIHRoZSBFTEEgc2NvcmVzIGZyb20gMyB0byA4IGdyYWRlcywgb3IgZm9yIHRoZSBncmFkdWF0aW9uIHJhdGUgaW4gaGlnaCBzY2hvb2wuCgpUaGlzIGNvbmNsdXNpb24gYWN0dWFsbHkgbWF0Y2hlcyB3aXRoIGEgbG90IG9mIGN1cnJlbnQgcmVzZWFyY2hlcyB3aGljaCBoYXZlIGZvdW5kIG91dCB0aGF0CmZlbWFsZSBzdHVkZW50cyB0ZW5kIHRvIHBlcmZvcm0gYmV0dGVyIHRoYW4gbWFsZSBzdHVkZW50cywgaW5jbHVkaW5nIHRvIGJlIG1vcmUgZW5nYWdlZCB3aXRoIHNjaG9vbCwgdG8gZ2V0IGEgYmV0dGVyIGFjYWRlbWljIGFjaGlldmVtZW50LCB0byBsZXNzIGRyb3BvdXQgYW5kIHRvIGdldCBoaWdoZXIgc2NvcmVzIGluIHJlYWRpbmcsIG1hdGgsIGFuZCBzY2llbmNlLgoKV2UgYmVsaWV2ZSB0aGVyZSBhcmUgdHdvIG1ham9yIHJlYXNvbnMuIFRoZSBmaXJzdCBvbmUgaXMgcmVsYXRlZCB0byBuYXR1cmUgYW5kIGhhYml0IGRpZmZlcmVuY2UgYmV0d2VlbiBtYWxlcyBhbmQgZmVtYWxlcywgZm9yIGZlbWFsZXMgYXJlIG1vcmUgZ29hbC1vcmllbnRhdGVkIGFuZCBoYXZlIG1vcmUgc2VsZi1yZWd1bGF0aW9uLCB3aGljaCBmaXRzIHdlbGwgaW50byB0aGUgc2Nob29sIGxpdmVzLiBBbm90aGVyIHJlYXNvbiBpcyByZWxldmFudCB0byB0aGUgZWR1Y2F0aW9uIHBvbGljeSBhbmQgZmVtaW5pc3QgbW92ZW1lbnQsIGJ5IHdoaWNoIGZlbWFsZXMgYXJlIHNvbWVob3cgZ2V0dGluZyBhIGJpdCBtb3JlIGF0dGVudGlvbiB0aGFuIG1hbGVzLiBGb3IgaW5zdGFuY2UsIHRoZXJlIGFsc28gZXhpc3RzIGEg4oCcUmVzcGVjdCBmb3IgYWxsCuKAnHJ1bGUgKGh0dHA6Ly9zY2hvb2xzLm55Yy5nb3YvUnVsZXNQb2xpY2llcy9SZXNwZWN0Zm9yQWxsL0NvbW1pdG1lbnQvZGVmYXVsdC5odG0pIHNldCBieSBOWUMgZGVwYXJ0bWVudCBvZiBlZHVjYXRpb24gd2hpY2ggc3RhdGVzIHRoYXQg4oCcVGhlIE5ZQ0RPRSBpcyBjb21taXR0ZWQgdG8gbWFpbnRhaW5pbmcgYSBzYWZlIGFuZCBzdXBwb3J0aXZlIGxlYXJuaW5nIGVudmlyb25tZW50IHRoYXQgaXMgZnJlZSBmcm9tIGhhcmFzc21lbnQsIGludGltaWRhdGlvbiBhbmQvb3IgYnVsbHlpbmcgYW5kIGZyb20gZGlzY3JpbWluYXRpb24gYmFzZWQgb24gYWN0dWFsIG9yIHBlcmNlaXZlZCByYWNlLCBjb2xvciwgY2l0aXplbnNoaXAvaW1taWdyYXRpb24gc3RhdHVzLCByZWxpZ2lvbiwgY3JlZWQsIG5hdGlvbmFsIG9yaWdpbiwgZGlzYWJpbGl0eSwgZXRobmljaXR5LCBnZW5kZXIsIGdlbmRlciBpZGVudGl0eSwgZ2VuZGVyIGV4cHJlc3Npb24sIHNleHVhbCBvcmllbnRhdGlvbiwgb3Igd2VpZ2h0LuKAnQoKQWx0aG91Z2ggZmVtYWxlcyBhcmUgbW9yZSBsaWtlbHkgdG8gb3V0cGVyZm9ybSBtYWxlcyBpbiB3aGV0aGVyIHByaW1hcnkgc2Nob29scyBvciBoaWdoIHNjaG9vbHMgZm9yIG1hdGgsIHJlYWRpbmcsIGFuZCB3cml0aW5nLiBUaGVyZSBpcyBhIHJlc2VhcmNoIHJlcG9ydCDigJxCZXR0ZXIgVGVzdCBTY29yZXMgQ291bGQgTWVhbiBUcmlsbGlvbnMgb2YgRG9sbGFycyBmb3IgdGhlIFUuUy4gRWNvbm9teeKAnSAoaHR0cHM6Ly93d3cudXNuZXdzLmNvbS9uZXdzL2FydGljbGVzLzIwMTUvMDIvMDMvYmV0dGVyLXRlc3Qtc2NvcmVzLWNvdWxkLW1lYW4tdHJpbGxpb25zLW9mLWRvbGxhcnMtZm9yLXRoZS11cy1lY29ub215KSB3aGljaCBmb3VuZCBvdXQgdGhhdCBmZW1hbGVzIHdlcmUgbW9yZSBsaWtlbHkgdGhhbiBib3lzLCB0byBoYXZlIGxvd2VyIHNlbGYtY29uZmlkZW5jZSBpbiB0aGVpciBtYXRoIHNraWxscyBhbmQgbW9yZSBsaWtlbHkgdG8gZmVlbCBhbnhpb3VzIGFib3V0IGFwcGx5aW5nIG1hdGggaW4gdGhlIGhpZ2hlciBlZHVjYXRpb24gZmllbGQgYW5kIGV2ZW4gdGhlaXIgY2FyZWVycy4KCkZvciB0aGlzIHByb2JsZW0sIHRoZSBlZmZvcnQgYnkgcGFyZW50cywgc2Nob29scywgYW5kIHBvbGljeW1ha2VycyBpcyByZXF1aXJlZCB0byBoZWxwIGJvdGggbWFsZXMgYW5kIGZlbWFsZXMgcmVhbGl6ZSB0aGVpciBmdWxsIHBvdGVudGlhbCBpbiBvcmRlciB0byBsZXQgdGhlbSBtYWtlIGEgYmlnZ2VyIGNvbnRyaWJ1dGlvbiB0byB0aGUgd2VsbCDigJMgYmVpbmcgb2YgdGhlIHNvY2lldHkuIEZvciBpbnN0YW5jZSwgdG8gbmFycm93IHRoZSBhY2FkZW1pYyBnYXAgYmV0d2VlbiBtYWxlcyBhbmQgZmVtYWxlcywgc2Nob29scyBjb3VsZCBhZGp1c3QgdGhlaXIgdGVhY2hpbmcgbWV0aG9kcyBsaWtlIGVzdGFibGlzaGluZyBzcGVjaWFsIGNvdXJzZXMgd2l0aCBtb3JlIGNvbnRlbnRzIGFib3V0IHdhcnMgYW5kIHNjaWVuY2UgZmljdGlvbnMgZm9yIG1hbGUgc3R1ZGVudHMuIE1vcmVvdmVyLCB0byBoZWxwIGZlbWFsZSBzdHVkZW50cyByZWFsaXplIHRoZWlyIHBvdGVudGlhbCBpbiBtYXRoLCBOWUMgZGVwYXJ0bWVudCBvZiBlZHVjYXRpb24gY291bGQgb3JnYW5pemUgc2Nob29scyB0byBoZWxkIHVwIHdvcmtzaG9wcyBhbmQgc2VtaW5hcnMgd2l0aCBhIHRvcGljIG9mIG1hdGggYW5kIHNjaWVuY2UgdG8gYXJvdXNlIHRoZWlyIGludGVyZXN0IGluIG1hdGggYW5kIHNjaWVuY2UuCgojIyMgYykgU1dEIEFuYWx5c2lzIGFuZCBQb2xpY3kKCkZyb20gYW5hbHlzaXMgYWJvdmUsIGl0IGlzIGFwcGFyZW50IHRoYXQgZHVlIHRvIHRoZSBkaXNhYmlsaXR5LCBzdHVkZW50cyB3aXRoIGRpc2FiaWxpdHkgcGVyZm9ybSByZW1hcmthYmx5IHdvcnNlIHRoYW4gc3R1ZGVudHMgd2l0aG91dCBkaXNhYmlsaXR5LiBUaGUgZ292ZXJubWVudCBhbmQgc2Nob29scyBzaG91bGQgcGF5IG1vcmUgYXR0ZW50aW9uIHRvIHN0dWRlbnRzIHdpdGggZGlzYWJpbGl0eSB0byBoZWxwIHRoZW0gb3ZlcmNvbWUgb2JzdGFjbGVzIG9mIGxlYXJuaW5nIGFuZCBnZXQgYSBiZXR0ZXIgbGlmZS4KCiMjIyBkKSBFbmdsaXNoIExhbmd1YWdlIExlYXJuZXIoRUxMKSBBbmFseXNpcyBhbmQgcG9saWN5CldlIGNhbiBmaWd1cmUgb3V0IHRoZSBmYWN0IHRoYXQgZnJvbSBHcmFkZSAzIHRvIDEyLCBmb3JtZXIgRUxMcyBwZXJmb3JtcyBtdWNoIGJldHRlciB0aGFuIEVMTHMgYW5kIHNpbWlsYXJseSBhcyB0aGUgcGVyZm9ybWFuY2Ugb2YgRVAoRW5nbGlzaCBQcm9maWNpZW50KS4gVGhlIGZhc3QgaW1wcm92ZW1lbnRzIG9uIEVMTHPigJkgYWNhZGVtaWMgcGVyZm9ybWFuY2VzIG1heSBiZSBjYXVzZWQgYnkgdGhlIHN1cHBvcnRzIG9mIE5ZQyBEZXBhcnRtZW50IG9mIEVkdWNhdGlvbi4KTllDIERlcGFydG1lbnQgb2YgRWR1Y2F0aW9uIHByZXBhcmVzIChOWUNET0UpdGhlIFN1bW1lciBFbnJpY2htZW50IFByb2dyYW1zIGZvciBFbmdsaXNoIExhbmd1YWdlIExlYXJuZXIoRUxMKS4g4oCcRUxMcyBpbiBncmFkZXMgMi04IGNhbiBwYXJ0aWNpcGF0ZSBpbiBtYXRoLCBzY2llbmNlLCBhbmQgcmVhZGluZyBhbmQgd3JpdGluZyBhY3Rpdml0aWVzIGR1cmluZyB0aGUgc3VtbWVyLiBUaGUgRE9FIGFsc28gb2ZmZXJzIHN1bW1lciBsZWFybmluZyBvcHBvcnR1bml0aWVzIGZvciBFTEwgc3R1ZGVudHMgaW4gaGlnaCBzY2hvb2wgd2hvIGFyZSBvbiB0cmFjayB0byBncmFkdWF0ZS7igJ0gKEZyb20gRE9FIE9mZmljaWFsIFdlYnNpdGU6IGh0dHA6Ly9zY2hvb2xzLm55Yy5nb3YvQWNhZGVtaWNzL0VMTC9kZWZhdWx0Lmh0bSkKTW9yZW92ZXIsIE5ZQ0RPRSBhbHNvIHByb3ZpZGUgZGlmZmVyZW50IGtpbmRzIG9mIEVMTHMgZm9yIHZhcmlvdXMgaGVscCBvbiB0aGVpciBFbmdsaXNoIHN0dWR5LiDigJxUaGV5IG9mZmVycyB0aHJlZSBzZXJ2aWNlIGRlbGl2ZXJ5IG1vZGVsczogZHVhbCBsYW5ndWFnZSAoREwpLCB0cmFuc2l0aW9uYWwgYmlsaW5ndWFsIGVkdWNhdGlvbiAoVEJFKSwgYW5kIEVuZ2xpc2ggYXMgYSBuZXcgbGFuZ3VhZ2UgKEVOTCAxMSkuIFRoZXNlIG1vZGVscyBhcmUgZGVzaWduZWQgdG8gcHJvbW90ZSBwcm9maWNpZW5jeSBpbiBhIHN0dWRlbnTigJlzIGhvbWUgbGFuZ3VhZ2UgYW5kIEVuZ2xpc2guIFBhcmVudHMgb3IgZ3VhcmRpYW5zIG9mIEVMTHMgYXJlIGVudGl0bGVkIHRvIGNob29zZSBhbnkgb2YgdGhlc2Ugc2VydmljZSBkZWxpdmVyeSBtb2RlbHMgZm9yIHRoZWlyIGNoaWxkIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGVpciB6b25lZCBzY2hvb2wgaGFzIHRoZWlyIHByb2dyYW0gb2YgY2hvaWNlIGN1cnJlbnRseSBhdmFpbGFibGUu4oCdIChGcm9tIERPRSBvZmZpY2lhbCByZXBvcnQ6IGh0dHA6Ly9zY2hvb2xzLm55Yy5nb3YvTlIvcmRvbmx5cmVzLzAxODNENTFDLTM3N0ItNEVENy1CQ0JFLTYwN0FFNDY2OUQ1NC8wLzIwMTQxNUVMTERlbW9ncmFwaGljUmVwb3J0LnBkZiApCiAKIyMjIGUpIFRoZSBwb3NzaWJsZSBjb3JyZWxhdGlvbiBvbiBJbmNvbWUgYW5kIHN0dWRlbnRz4oCZIEFjYWRlbWljIHBlcmZvcm1hbmNlCldlIGh5cG90aGVzaXplZCB0aGF0IHRoZSByZWdpb24gd2l0aCBoaWdoZXIgaW5jb21lIG1heSBiZSB3aXRoIGJldHRlciBzdHVkZW50c+KAmSBhY2FkZW1pYyBwZXJmb3JtYW5jZXMuIFNvLCB3ZSBjb21wYXJlZCB0aGUgbWFwIHdpdGggZ3JhZHVhdGlvbiByYXRlIGFuZCBpbmNvbWUoaHR0cDovL3d3dy5idXNpbmVzc2luc2lkZXIuY29tL25ldy15b3JrLWNpdHktaW5jb21lLW1hcHMtMjAxNC0xMiApLCBhbmQgdmFsaWRhdGVkIG91ciBoeXBvdGhlc2lzLiAKCiFbXShoZWF0bWFwX2NvbXBhcmlzb24ucG5nKQpBcHBhcmVudGx5LCBkYXJrZXIgcGxhY2VzKHdpdGggaGlnaGVyIGdyYWR1YXRpb24sIGFuZCB3aXRoIGhpZ2hlciBpbmNvbWUpIGFuZCBsaWdodGVyIHBsYWNlcyBvZiBHcmFkdWF0aW9uIFJhdGUgYW5kIE5ZQyBJbmNvbWUgbWF0Y2ggdG8gZWFjaCBvdGhlci4KCiMjIyBmKSBTY2hvb2wgQW5hbHlzaXMKRnJvbSB0aGUgdmlzdWFsaXphdGlvbiBvZiBzY2hvb2wgcGVyZm9ybWFuY2UgZGF0YSwgd2UgY291bGQgZmluZCB0aGF0IHRoZSBwZXJmb3JtYW5jZSBvZiBzY2hvb2xzIGluIERpc3RyaWN0IDIsIDIwIGFuZCAyNiBhcmUgcmVtYXJrYWJseSBiZXR0ZXIgdGhhbiB0aG9zZSBpbiBvdGhlciBkaXN0cmljdHMsIHdoaWNoIG1lYW5zIHRoYXQgc3R1ZGVudHMgaW4gdGhlc2UgZGlzdHJpY3RzIGNhbiBnZXQgbW9yZSBmcm9tIHNjaG9vbCBlZHVjYXRpb24gYW5kIHRoZWlyIGxlYXJuaW5nIGlzIGFjY2VsZXJhdGVkIG1vcmUgZWZmaWNpZW50bHkuIFRoaXMgY291bGQgYmUgYSBzaWduaWZpY2FudCByZWFzb24gZm9yIGJldHRlciBzdHVkZW50IHBlcmZvcm1hbmNlIGluIHRoZXNlIHR3byBkaXN0cmljdHMuIFNpbWlsYXJseSwgc3R1ZGVudHMgcGVyZm9ybSB3b3JzZSBpbiBkaXN0cmljdHMgd2hlcmUgc2Nob29sIHBlcmZvcm0gd29yc2Ugc3VjaCBhcyBEaXN0cmljdCAyMy4KClBhcmVudHMgY2FuIHNlbmQgdGhlaXIgY2hpbGRyZW4gdG8gZGlzdHJpY3RzIHdoZXJlIHNjaG9vbHMgcGVyZm9ybSBiZXR0ZXIgdGhhbiBvdGhlciBkaXN0cmljdHMgdG8gbWFrZSB0aGVpciBjaGlsZHJlbiBzdHVkeSBpbiBiZXR0ZXIgZWR1Y2F0aW9uIGVudmlyb25tZW50IGFuZCBnZXQgYmV0dGVyIGdyYWRlLiAgIApUaGUgZ292ZXJubWVudCBzaG91bGQgcGF5IG1vcmUgYXR0ZW50aW9uIHRvIGRpc3RyaWN0cyB3aGVyZSBzY2hvb2xzIHBlcmZvcm0gd29yc2UgdG8gbWFrZSBzdXJlIHRoZSBlcXVhbCBhY2Nlc3MgdG8gZWR1Y2F0aW9uLgoKIyA2LiBDb25jbHVzaW9uCgojIyAoMSkgTGltaXRhdGlvbnMgCgpBbHRob3VnaCB3ZSBkdWcgZGVlcGx5IG9uIG91ciBkYXRhc2V0cywgbWFkZSBpbnNpZ2h0ZnVsIGFuYWx5c2VzIGluIHRoZSBLLTEyIGVkdWNhdGlvbiBvZiBOWUMgYW5kIGNvbnN0cnVjdGVkIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBvcmlnaW5hbCBkYXRhIGFuZCBzb2NpYWwgbWF0dGVycywgb3VyIHByb2dyYW0gc3RpbGwgaGFzIHNvbWUgbGltaXRhdGlvbnMuIEZvciB0aGUgcGVyc3BlY3RpdmUgb2YgZGF0YSwgd2UgY2Fubm90IGdhdGhlciBjb21wbGV0ZSBkYXRhIGZyb20gdGhlIHllYXIgMjAwMSB0byAyMDE2IGluIGFsbCBhc3BlY3RzIHdlIGFuYWx5emVkLiBGb3IgZXhhbXBsZSwgd2hlbiB3ZSBkaXNjdXNzIHRoZSBncmFkdWF0aW9uIHJhdGUgc2l0dWF0aW9uLCB0aGUgZGF0YSBmcm9tIDIwMTMgdG8gMjAxNiBpcyB1bmF2YWlsYWJsZS4gVGhpcyBjaXJjdW1zdGFuY2UgcmVzdHJpY3RlZCBvdXIgY29tcHJlaGVuc2l2ZSBjb21wYXJpc29uIGFtb25nIGFsbCBhc3BlY3RzIG92ZXIgdGhlc2UgeWVhcnMuIEZvciB0aGUgcGVyc3BlY3RpdmUgb2YgYW5hbHlzaXMgb24gdGhlIGRhdGFzZXQsIHdlIGFsd2F5cyBjaG9zZSBtZWFuIHZhbHVlIGFzIG9iamVjdHMgdG8gY29tcGFyZSwgeWV0IHRoZXNlIG1ldGhvZHMgbWF5IGhhdmUgYmlhc2VzIGluIHNvbWUgc2l0dWF0aW9uLiBXZSBleHBlY3QgdG8gdXNlIG1vcmUgc3RhdGlzdGljcyB0byBhbmFseXplIHRoZSBkYXRhIGluIGZ1dHVyZS4gRm9yIHRoZSBwZXJzcGVjdGl2ZSBvZiBhbmFseXNlcyB3aXRoIHNvY2lhbCBtYXR0ZXJzLCB3ZSBjb21wYXJlZCBhbmQgZm91bmQgdGhlIHBvc3NpYmxlIG1hdHRlcnMgcmVsZXZhbnQgdG8gdGhlIHBoZW5vbWVub24gYnV0IGNhbm5vdCBtYWtlIHN1cmUgdGhlIGNhdXNhbCByZWxhdGlvbnNoaXAuIFdlIGNvdWxkIHVzZSBjYXVzYWwgaW5mZXJlbmNlIGtub3dsZWRnZSB0byBtYWtlIG91ciBjb25jbHVzaW9uIG1vcmUgdmFsaWQuIEZvciB0aGUgcGVyc3BlY3RpdmUgb2YgdGVjaG5pcXVlIHNraWxscyB3ZSB1c2VkIGluIHRoaXMgcHJvamVjdCwgd2UgdXRpbGl6ZWQgc29tZSBlZmZpY2llbnQgYW5kIGFjY3VyYXRlIG1ldGhvZHMgeWV0IHN0aWxsIGhhdmUgcm9vbSB0byBpbXByb3ZlLiAKCgojIyAoMikgRnV0dXJlIGRpcmVjdGlvbjogCkluIG5leHQgc3RlcCwgd2UgY2FuIGNvbnRhY3QgdGhlIGRlcGFydG1lbnQgb2YgZWR1Y2F0aW9uIG9mIE5ZQyB0byBnYXRoZXIgbW9yZSBjb21wbGV0ZSBkYXRhIHRvIGltcHJvdmUgb3VyIGFuYWx5c2lzLiBGb3IgdGhlIHBlcnNwZWN0aXZlIG9mIGFuYWx5c2lzIG9uIHRoZSBkYXRhc2V0LCB3ZSBjb3VsZCBhbmFseXplIHRoZSBzY29yZXMgbWV0aWN1bG91c2x5LCBlLmcuIGFuYWx5emUgdGhlIHNjb3JlIG9mIGVhY2ggZ3JhZGUgcmVzcGVjdGl2ZWx5LiBEZWVwZXIgaW5zaWdodCBpbnRvIE5ZQyBLLTEyIGRhdGEgY291bGQgYmUgb2J0YWluZWQgYnkgYW5hbHl6aW5nIG1vcmUgcmVsYXRpdmUgZGF0YSBiZXNpZGVzIHRoZSBpbmNvbWUgbGV2ZWwsIGluY2x1ZGluZyB0aGUgZWR1Y2F0aW9uIGxldmVscyBvZiBwYXJlbnRzLCB0aGUgY29tbXVuaXR5IGVudmlyb25tZW50LCB0aGUgY3JpbWUgcmF0ZSwgZXRjLiAsIGFuZCByZXNlYXJjaCBvbiB0aGVpciBpbmZsdWVuY2Ugb24gc3R1ZGVudCBwZXJmb3JtYW5jZS4gVGhlbiB3ZSBjb3VsZCByZWFkIHNvbWUgcmVsYXRpdmUgcGFwZXJzIHRvIHZhbGlkYXRlIG91ciBjb25jbHVzaW9uIGRyYXduIGZyb20gZGF0YSBhbmFseXNpcy4gCkZ1cnRoZXJtb3JlLCB3ZSBjYW4gZXh0ZW5kIG91ciBLLTEyIGVkdWNhdGlvbiBhbmFseXNpcyB0byBvdGhlciBjaXRpZXMgaW4gdGhlIFN0YXRlcyB0byBmaW5kIG91dCB0aGUgZGlmZmVyZW5jZXMgb2YgSy0xMiBlZHVjYXRpb24gYW1vbmcgZGlmZmVyZW50IGNpdGllcywgdGhlbiBleHBsb3JlIGFuZCBnZW5lcmFsaXplIHRoZSBpbmZsdWVuY2UgZmFjdG9yIG9mIEstMTIgZWR1Y2F0aW9uLiBXZSBjYW4gZXZlbiBleHRlbmQgdGhlIHByb2plY3QgdG8gdGhlIHdob2xlIHdvcmxkIGFuZCBjb21wYXJlIHRoZSBLLTEyIGVkdWNhdGlvbiBvZiBkaWZmZXJlbnQgY291bnRyaWVzIGFsbCBvdmVyIHRoZSB3b3JsZC4gVGhhdCB3b3VsZCBiZSBhIGdyZWF0IGFuZCBtZWFuaW5nZnVsIHByb2plY3QgdGhlbi4KCiMjICgzKSBMZXNzb24gTGVhcm5lZDogCldlIGxlYXJuZWQgYSBsb3QgZHVyaW5nIG91ciBwcm9jZWR1cmUgb2YgdGhpcyBwcm9qZWN0LiBFYWNoIG9mIHVzIHRyaWVkIHRvIGZpbmQgdHdvIHRvcGljcyBhbmQgcmVsYXRlZCBkYXRhc2V0cyBhdCB0aGUgYmVnaW5uaW5nIGFuZCB3ZSBzZWxlY3RlZCBvdXIgbW9zdCBpbnRlcmVzdGluZyB0b3BpY3MgYWZ0ZXIgZG9pbmcgYnJpZWYgaW50cm9kdWN0aW9ucyBmb3Igb3VyIGlkZWFzLiBUaGlzIGV4cGVyaWVuY2UgbWFkZSB1cyBsZWFybiBob3cgdG8gZmluZCBhIHByb3BlciBkYXRhc2V0IGFuZCBkZXNpZ24gYSBwcm9qZWN0IGF0IGZpcnN0LiBEdXJpbmcgb3VyIHByb2plY3QsIHdlIG1lZXQgdHdpY2UgYSB3ZWVrIHRvIGNvbW11bmljYXRlIG91ciBtZXRob2RzIHRvIHBsb3QsIHRoZSBxdWFsaXR5IG9mIGdyYXBocyBhbmQgd2hldGhlciB0ZWFtbWF0ZXPigJkgZ3JhcGhzIG1hZGUgc2Vuc2UuIEdyYWR1YWxseSwgd2UgbGVhcm5lZCBob3cgdG8gZGVhbCB3aXRoIG1lc3N5IGRhdGEgd2l0aCBza2lsbHMgb2YgY2xlYW5pbmcsIHRyYW5zZm9ybWluZyBhbmQgbG9hZGluZyBhbmQgY2FuIGNob29zZSB0aGUgcHJvcGVyIG1ldGhvZHMgdG8gcGxvdCBhbmQgd3JpdGUgZGF0YSB2aXN1YWxpemF0aW9uIFIgY29kZSBlZmZpY2llbnRseS4gTW9yZW92ZXIsIHdlIGxlYXJuZWQgYnkgb3Vyc2VsdmVzIG9uIGhvdyB0byB1c2UgRDMgdG8gcGxvdCB0aGUgaW50ZXJhY3RpdmUgbWFwLCBpbmRpY2F0aW5nIG1vcmUgaW5mb3JtYXRpb24gZm9yIHRoZSB2aWV3ZXIuIEl0IGVuYWJsZXMgdXMgdG8gZG8gZnVydGhlciBtb3JlIGF0dHJhY3RpdmUgYW5kIGNsZWFyIGRhdGEgYW5hbHlzaXMuIEluIGFkZGl0aW9uLCBkdXJpbmcgb3VyIGFuYWx5c2VzLCB3ZSBsZWFybmVkIGhvdyB0byBwbG90IGFuZCByZWFkIHRoZSBncmFwaHMgaW4gc2ltcGxlciB3YXlzIGFuZCBob3cgY2FuIHdlIGJ1aWxkIGNvcnJlbGF0aW9ucyBvbiBzb2NpYWwgbWF0dGVycyBhbmQgb3VyIGRhdGEgdG8gaGVscCBkZWNpc2lvbiBtYWtlcnMgdG8gc29sdmUgcmVsYXRlZCBtYXR0ZXJzLiBEdXJpbmcgb3VyIHByb2plY3QsIHdlIHN0dWRpZWQgYm90aCB0ZWNobmlxdWUgc2tpbGxzIG9uIHZpc3VhbGl6YXRpb24gY29kaW5nIGFuZCBkYXRhIGFuYWx5c2VzLCB3aGljaCBidWlsZCBhIHNvbGlkIGZvdW5kYXRpb24gZm9yIG91ciBjYXJlZXIgcGF0aCB0byBkYXRhIHNjaWVudGlzdC4KCg==